我正在使用原生 promise (主要是)并尝试从错误中恢复并继续执行 promise 链。
实际上,我正在这样做:
- REST 查询以查看 ID 是否存在。 请注意,这会返回一个延迟的 jquery。
- .then(成功表示ID存在,失败停止) (失败表示ID不存在,继续创建ID)
- .then(创建ID记录并发送到服务器)
我从被拒绝的函数中返回一个 Promise.resolve() ,这应该会导致下一个 .then 的成功部分被执行。它不是。我已经在 Chrome 和 Safari 上试过了。
请注意,第一个 promise 实际上是一个延迟查询,但根据此页面(http://api.jquery.com/deferred.then/),deferred.then() 返回一个 promise 对象。因此,添加一个额外的 .then 应该可以隐藏到原生的 promises。
为了更清楚 - 这是伪代码:
promise = $.ajax(url);
promise = promise.then(); // convert to promise
promise.then(function() { cleanup(); return Promise.reject(); },
function(err) { return Promise.resolve(); });
.then(function() { createIdentityDetails(); });
.then(function() { sendIdentityDetails(); });
请注意,当 ajax 返回成功时,我想 FAIL,我想 当 ajax 调用失败时继续处理。
发生的是所有后续 .then 部分的 FAIL 函数都执行了。也就是说,我的 return Promise.resolve() 不起作用——这(我认为)违反了规范。
对于如何处理长 promise 链中的错误并从中恢复的任何反馈,我将不胜感激。
非常感谢您提供的任何建议。
附注创建和收集完整的身份信息非常耗时,所以如果 ID 存在,我不想这样做。因此我想先检查并快速失败。
p.p.s 我真的很喜欢 promises 解开这些深度嵌套的异步回调链的方式。
最佳答案
假设 createIdentityDetails()
和 sendIdentityDetails()
是 promise 返回的异步函数 ...
如果我们在问题中看到的是整个 promise 链,那么处理错误情况就很简单。没有必要将成功转化为失败或将失败转化为成功,或者从一种 promise 转变为另一种 promise 。
$.ajax(url).then(function() {
cleanup();
}, function(err) {
createIdentityDetails()
.then(sendIdentityDetails);
});
无论 createIdentityDetails()
jQuery 或非 jQuery 返回的 promise 类型如何,这都将起作用。
但是,如果还有更多内容,例如需要将结果告知调用函数,那么您需要做更多的事情,这取决于您希望如何报告可能的结果。
报告“ID 已存在”为失败,“已创建新 ID”为成功
这就是问题所暗示的
function foo() {
return $.ajax(url).then(function() {
cleanup();
return $.Deferred().reject('failure: ID already exists');
}, function(err) {
return createIdentityDetails()
.then(sendIdentityDetails)
.then(function() {
return $.when('success: new ID created');
});
});
}
将两种类型的结果都报告为成功
这似乎更明智,因为处理的错误将被报告为成功。只有不可预测的、未处理的错误才会被报告。
function foo() {
return $.ajax(url).then(function() {
cleanup();
return 'success: ID already exists';
}, function(err) {
return createIdentityDetails()
.then(sendIdentityDetails)
.then(function() {
return $.when('success: new ID created');
});
});
}
无论采用哪种报告策略,createIdentityDetails()
返回的 promise 类型都非常重要。作为链中的第一个 promise ,它决定了它所链接的 .thens 的行为。
- 如果
createIdentityDetails()
返回原生 ES6 promise,那么不用担心,大多数 promise 风格,甚至 jQuery,都会被吸收。 - 如果
createIdentityDetails()
返回一个 jQuery promise,那么只会吸收 jQuery promise。因此sendIdentityDetails()
还必须返回一个 jQuery promise(或者一个 ES6 promise,它必须用$.Deferred(...)
重铸成 jQuery),最后的也必须如此成功转换器(如上编码)。
您可以通过这两种方式查看混合 jQuery 和 ES6 promises 的效果 here .第一个警报由第二个代码块生成,不是预期的。第二个警报由第一个 block 生成,并正确给出结果 98 + 1 + 1 = 100。
关于javascript - 从 JS 中被拒绝的 promise 中恢复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31962655/