gpt4 book ai didi

javascript - 链式 promise 不会在拒绝时传递

转载 作者:IT老高 更新时间:2023-10-28 21:57:38 26 4
gpt4 key购买 nike

我无法理解为什么拒绝没有通过 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 链上,每一个都暗示着它将依赖于 d1 的成功解决和传递到链上的结果。如果promise1 中的promise 没有收到wins 值,而是在它的错误处理程序中得到了一个err 值,那么链中的下一个promise 怎么可能调用它的success 函数呢?它无法将有意义的值传递给下一个 Promise,因为它本身没有获得值。

我可以用另一种方式来描述我的想法:共有三个人,John、Ginger 和 Bob。约翰拥有一家小部件商店。 Ginger 走进他的商店,要了一袋颜色各异的小玩意儿。他没有库存,所以他向他的分销商发送请求,要求将它们运送给他。与此同时,他给了 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 的分辨率以及 然后回调处理它

文档状态:

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

.then 方法通常被视为 Promises/A specification (或更严格的 Promsises/A+ one )。这意味着回调 shell 返回的 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)来自 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/16371129/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com