javascript - 链式 promise 不会传递拒绝

标签 javascript node.js dojo promise deferred

我无法理解为什么拒绝不会通过 promise 链传递,我希望有人能够帮助我理解原因。对我来说,将功能附加到 promise 链意味着我依赖于要实现的原始 promise 的意图。这很难解释,所以让我先展示我的问题的代码示例。 (注意:这个例子使用的是 Node 和延迟 Node 模块。我用 Dojo 1.8.3 测试了这个并且得到了相同的结果)

var d = require("deferred");

var d1 = d();

var promise1 = d1.promise.then(
    function(wins) { console.log('promise1 resolved'); return wins;},
    function(err) { console.log('promise1 rejected'); return err;});
var promise2 = promise1.then(
    function(wins) { console.log('promise2 resolved'); return wins;},
    function(err) { console.log('promise2 rejected'); return err;});
var promise3 = promise2.then(
    function(wins) { console.log('promise3 resolved'); return wins;},
    function(err) { console.log('promise3 rejected'); return err;});
d1.reject(new Error());

运行这个操作的结果是这个输出:

promise1 rejected
promise2 resolved
promise3 resolved

好吧,对我来说,这个结果没有意义。通过附加到这个 promise 链,每个 then 都暗示了它的意图,即它将依赖于 d1 的成功解析和一个传递到链中的结果。如果 promise1 中的 promise 没有收到 wins 值,而是在其错误处理程序中获得了 err 值,那么链中的下一个 promise 怎么可能调用其成功函数?它无法将有意义的值传递给下一个 promise ,因为它本身没有获得值。

我可以用另一种方式来描述我的想法:有三个人,John、Ginger 和 Bob。约翰拥有一家小工具店。金杰走进他的店里,要了一袋各种颜色的小玩意儿。他没有库存,因此他向经销商发出请求,要求将它们运送给他。与此同时,他给了 Ginger 一张雨支票,说他欠她一袋小工具。 Bob 发现 Ginger 正在获取小部件,并请求他在她用完这些小部件后得到蓝色小部件。她同意并给了他一张纸条,说明她会的。现在,John 的经销商在他们的供应中找不到任何小部件,制造商也不再生产这些小部件,因此他们通知 John,John 又通知 Ginger 她无法获得这些小部件。 Bob 怎么能从 Ginger 那里得到一个蓝色的小部件,而她自己却没有?

我对这个问题的第三个更现实的观点是。假设我有两个值要更新到数据库。一个依赖于另一个的 id,但是在我已经将它插入数据库并获得结果之前我无法获得 id。最重要的是,第一个插入依赖于来自数据库的查询。数据库调用返回我用来将两个调用链接成一个序列的 promise 。

var promise = db.query({parent_id: value});
promise.then(function(query_result) {
    var first_value = {
        parent_id: query_result[0].parent_id
    }
    var promise = db.put(first_value);
    promise.then(function(first_value_result) {
        var second_value = {
            reference_to_first_value_id: first_value_result.id
        }
        var promise = db.put(second_value);
        promise.then(function(second_value_result) {
            values_successfully_entered();
        }, function(err) { return err });
    }, function(err) { return err });
}, function(err) { return err });

现在,在这种情况下,如果 db.query 失败,它将调用第一个 then 的 err 函数。但随后它会调用下一个 promise 的成功函数。虽然该 promise 期望第一个值的结果,但它会从其错误处理函数中获取错误消息。

所以,我的问题是,如果我必须在我的成功函数中测试错误,为什么我会有一个错误处理函数?

抱歉这么长。我只是不知道如何用另一种方式来解释它。

更新和更正

(注意:我删除了我曾经对一些评论做出的回复。因此,如果有人对我的回复发表评论,他们的评论现在可能看起来断章取义,因为我删除了它。对此感到抱歉,我试图将其保留为尽可能短。)

谢谢大家的回复。我想首先向大家道歉,因为我的问题写得如此糟糕,尤其是我的伪代码。我试图保持简短有点过于激进。

感谢 Bergi 的回复,我想我发现了我的逻辑错误。我想我可能忽略了导致我遇到的问题的另一个问题。这可能导致 promise 链的工作方式与我想象的不同。我仍在测试我的代码的不同元素,所以我什至无法形成一个正确的问题来查看我做错了什么。不过,我确实想向大家介绍最新情况,感谢您的帮助。

最佳答案

To me, this result doesn't make sense. By attaching to this promise chain, each then is implying the intent that it will be dependant upon the successful resolution of d1 and a result being passed down the chain

没有。您所描述的不是链,而只是将所有回调附加到 d1 .然而,如果你想用 then 链接一些东西, promise2 的结果取决于 promise1 的分辨率以及如何 then回调处理了它

文档状态:

Returns a new promise for the result of the callback(s).

.then通常根据 Promises/A specification 来看待方法(或更严格的 Promsises/A+ one )。这意味着回调 shell 返回 promise ,这些 promise 将被吸收成为 promise2 的决议。 , 如果没有成功/错误处理程序,则相应的结果将直接传递给 promise2 - 因此您可以简单地省略处理程序来传播错误。

然而,如果错误得到处理,结果 promise2被视为固定的,并将用该值实现。如果您不想这样,则必须重新- throw错误,就像在 try-catch 子句中一样。或者,您可以从处理程序返回一个(待)拒绝的 promise 。不确定 Dojo 拒绝的方式是什么,但是:

var d1 = d();

var promise1 = d1.promise.then(
    function(wins) { console.log('promise1 resolved'); return wins;},
    function(err) { console.log('promise1 rejected'); throw err;});
var promise2 = promise1.then(
    function(wins) { console.log('promise2 resolved'); return wins;},
    function(err) { console.log('promise2 rejected'); throw err;});
var promise3 = promise2.then(
    function(wins) { console.log('promise3 resolved'); return wins;},
    function(err) { console.log('promise3 rejected'); throw err;});
d1.reject(new Error());

How is Bob able to get a blue widget from Ginger when didn't get any herself?

他应该做不到。如果没有错误处理程序,他只会感知到消息(((来自 John 的分销商)来自 Ginger),即没有剩余的小部件。然而,如果 Ginger 为这种情况设置了一个错误处理程序,那么如果 John 或他的分销商没有蓝色的,她仍然可以履行她的 promise ,通过从她自己的小屋给他一个绿色的小部件来给 Bob 一个小部件。

将您的错误回调转换为隐喻,return err来自处理程序的信息就像是在说“如果没有剩余的小部件,只需告诉他没有剩余的小部件 - 它与所需的小部件一样好”。

In the database situation, if the db.query failed, it would call the err function of the first then

…这意味着错误在那里被处理。如果你不这样做,就省略错误回调。顺便说一句,你的成功回调不会return他们正在创造的 promise ,因此它们似乎毫无用处。正确的是:

var promise = db.query({parent_id: value});
promise.then(function(query_result) {
    var first_value = {
        parent_id: query_result[0].parent_id
    }
    var promise = db.put(first_value);
    return promise.then(function(first_value_result) {
        var second_value = {
            reference_to_first_value_id: first_value_result.id
        }
        var promise = db.put(second_value);
        return promise.then(function(second_value_result) {
            return values_successfully_entered();
        });
    });
});

或者,因为您不需要闭包来访问先前回调的结果值,甚至:

db.query({parent_id: value}).then(function(query_result) {
    return db.put({
        parent_id: query_result[0].parent_id
    });
}).then(function(first_value_result) {
    return db.put({
        reference_to_first_value_id: first_value_result.id
    });
}.then(values_successfully_entered);

关于javascript - 链式 promise 不会传递拒绝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33956911/

相关文章:

DataGrid 的 Dojo 滚动问题

javascript - 获取数组的值

javascript - Grunt Concat Task,如何忽略所有 .min.js 文件?

javascript - Jquery css 函数在动画完成处理程序中不起作用

javascript - 插入到数据库进程后的sequelize.js 不退出/关闭

javascript - npm 模块依赖关系图不相似

javascript - 为创建 react 应用程序设置代理服务器

javascript - 我找不到访问 dGrid 商店的简单方法

javascript - 在javascript中从内存中删除对象

javascript - Chartjs如何从数据库动态更新数据(Chartjs无法获取数据)