Javascript 如何为一个承诺多次成功回调?
我有一个函数Javascript 如何为一个承诺多次成功回调?,javascript,promise,Javascript,Promise,我有一个函数loadItems(),它异步加载一些东西,然后失败或成功。fail和success回调都必须在库中执行某些操作,然后将其传递给实现者,实现者可以选择实现fail、success、两者都执行,或者不执行 我现在遇到的问题是,如果库同时实现了成功和失败处理程序,它将始终返回一个新的承诺来解决成功问题 这就是我所拥有的: // The library: function loadItems() { return store.get('todo').then(function(rs
loadItems()
,它异步加载一些东西,然后失败或成功。fail和success回调都必须在库中执行某些操作,然后将其传递给实现者,实现者可以选择实现fail、success、两者都执行,或者不执行
我现在遇到的问题是,如果库同时实现了成功和失败处理程序,它将始终返回一个新的承诺来解决成功问题
这就是我所拥有的:
// The library:
function loadItems() {
return store.get('todo').then(function(rsp) {
// Save these locally
items = rsp.value || [];
}, function(rsp) {
// Do nothing, but let the user know
alert(rsp.error);
});
}
store.get('todo')
(来自另一个库)返回一个承诺<代码>加载项()无法控制它
// The library implementer:
function init() {
loadItems().then(showItems);
}
我想要和期望发生的事情:
loadItems()
从库中运行异步代码(store.get()
)成功
和失败
,因为它们具有强制操作成功
,因为它不关心错误,因为库处理了错误.then(onSuccess)
来“添加另一个成功回调”store.get()
)也希望处理错误(用于偷偷记录),然后传递成功/失败
我的“解决方案”:
loadItems()
”失败回调引发错误。不幸的是,这意味着init()。不酷
init()
,而不是承诺,承诺只在成功后才会触发。这不好,因为有一天init()
可能会选择处理错误我肯定我做错了什么,但我看不出来。如果您想让拒绝处理程序根据错误执行某些操作,但仍希望返回的承诺被拒绝,只需在拒绝处理代码后重新显示错误(或返回拒绝的承诺)。这将允许拒绝通过返回的承诺传播回来
// The library:
function loadItems() {
return store.get('todo').then(function(rsp) {
// Save these locally
items = rsp.value || [];
}, function(rsp) {
// Do nothing, but let the user know
alert(rsp.error);
// rethrow the error so the returned promise will still be rejected
throw(rsp);
});
}
提供不抛出或返回被拒绝承诺的拒绝处理程序将告诉承诺系统您已“处理”错误,并且拒绝处理程序的返回值将成为承诺的新实现值。因此,如果您希望拒绝“保持”承诺,但希望处理程序根据拒绝做一些事情(记录拒绝是很常见的),那么您必须在拒绝处理程序中重新显示错误或返回被拒绝的承诺
// The library:
function loadItems() {
return store.get('todo').then(function(rsp) {
// Save these locally
items = rsp.value || [];
}, function(rsp) {
// Do nothing, but let the user know
alert(rsp.error);
// rethrow the error so the returned promise will still be rejected
throw(rsp);
});
}
虽然这在一开始看起来可能违反直觉,但它为您提供了最大的灵活性,因为您可以完全处理错误并让返回的承诺“成功”得到解决,或者您可以选择告诉承诺系统您想要传播错误,甚至可以选择要传播的错误(不一定是相同的错误)
你的问题中关于多个成功处理程序的部分让我有点困惑。你可以很容易地在任何承诺下拥有多个成功处理程序:
var p = someFuncThatReturnsSuccessfulPromise();
p.then(someSuccessHandler);
p.then(someOtherSuccessHandler);
如果p
是一个成功解析的承诺,那么这两个成功处理程序都将按照其附加的顺序被调用,并且someSuccessHandler
中发生的事情将不会影响是否调用someOtherSuccessHandler
。如果原始承诺被成功解析,那么两个处理程序都将被调用我会一直被召唤
如果您链接成功处理程序,那么这是一个完全不同的用例。这是完全不同的:
var p = someFuncThatReturnsSuccessfulPromise();
p.then(someSuccessHandler).then(someOtherSuccessHandler);
因为第二个.then()
处理程序没有附加到p
,而是附加到p.then(someSuccessHandler)
,这是一个不同的承诺,其结果可能会受到someSuccessHandler
中发生的事情的影响
问题中的代码已链接。您返回:
return store.get().then(...)
因此,当调用方链接到该链接上时,完整的链接是:
return store.get().then(yourhandler).then(theirhandler)
通过这种方式,yourhandler
可以影响传递给他们的Handler
的结果
除了我的第一个建议,即重新引用错误,您还可以这样做:
// The library:
function loadItems() {
var p = store.get('todo');
p.then(function(rsp) {
// Save these locally
items = rsp.value || [];
}, function(rsp) {
// Do nothing, but let the user know
alert(rsp.error);
});
return p;
}
在这里,您需要确保处理程序不会影响返回的内容。如果处理程序中没有任何异步操作,并且没有试图更改原始
store.get()的已解析值或已拒绝错误,则可以执行此操作
promise。我通常不建议这样做,因为如果处理程序正在执行其他异步操作或希望影响返回值,这会导致问题,但也可以在适当的情况下使用它。请阅读以下内容:您使用的是什么promise实现?“不幸的是,这意味着init()必须捕获它(或是浏览器抱怨)。不酷。“-不知道你的意思。拒绝承诺就像是这方面的一个例外,而这似乎正是你想要的?@CarlosCarucce我没有使用jQuery。@Bergi我在Chrome中使用本机承诺。我不想让每个“实现者”都处理错误,因为错误已经由loadItems()
init()处理了
只关心有效的结果。如果无效,则无所谓,但不要像有效一样执行then()
。@Deux-这回答了你的问题吗?我尝试了最后一件事(返回原始承诺),但我仍然从Chrome收到“承诺中的未捕获错误”警告。我想这就是我想要的