javascript - 从 JS 中被拒绝的 promise 中恢复

标签 javascript jquery deferred

我正在使用原生 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/

相关文章:

javascript - babel 在构建时无法编译成 ES5 的 ES6 特性是什么?

javascript - 在 JavaScript 中从字符串的开头到结尾删除 HTML 内容组

javascript - 限制特定列的单击事件

Javascript then() 链接 - 第二个 then() 对应哪个 Deferred?

javascript - 如何将这个延迟风格的 promise 转换为 ES6 风格的 promise

python - 如何 pickle 回调链

javascript - 如何从 HTA 在默认 Web 浏览器中打开链接?

javascript - 寻找适用于 Apple 类型下拉列表/菜单的 CSS

jquery - 在不裁剪的情况下缩放 iFrame/对象

javascript - 动画不工作,使用关键帧,无前缀