链接的承诺不会被拒绝 [英] Chained promises not passing on rejection

查看:156
本文介绍了链接的承诺不会被拒绝的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题,了解为什么拒绝不通过承诺链传递,我希望有人能够帮助我理解为什么。对我来说,将功能附加到一系列承诺意味着我依赖于一个原始的承诺来实现。这很难解释,所以让我先来看一下我的问题的代码示例。 (注意:这个例子是使用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;},
函数(err){console.log('promise2拒绝'); return err;});
var promise3 = promise2.then(
function(wins){console.log('promise3 resolved'); return wins;},
function(err){console.log('promise3拒绝'); return err;});
d1.reject(new Error());

运行此操作的结果是此输出:

  promise1被拒绝
promise2已解决
promise3已解决

对我来说,这个结果没有意义。通过附加到这个承诺链,每个都意味着它将取决于d1的成功解决,并将结果传递给链。如果promise1中的承诺没有获得胜利值,而是在其错误处理程序中获取错误值,那么链中的下一个承诺如何才能成功调用它呢?没有办法可以传递一个有意义的价值给下一个承诺,因为它没有获得一个价值本身。



一种不同的方式,我可以描述我是什么思想是:有三个人,约翰,姜,鲍勃。约翰拥有一个小工具店。姜进入他的商店,并要求一袋各种各样的颜色。他没有他们的库存,所以他要求他的经销商把他们运到他。同时,他给了姜一个雨检,说明他欠她一袋小部件。 Bob发现Ginger正在获得这些小部件,并要求在完成它们后获得蓝色小部件。她同意并给他一个说明她会的说明。现在,约翰的经销商在他们的供应中找不到任何小部件,制造商不再让他们了,所以他们通知约翰,谁反过来告诉姜,她不能得到小部件。当没有得到任何自己的时候,鲍勃能怎么得到一个蓝色的小部件呢?



在这个问题上,第三个更现实的观点就是这样。说我有两个值要更新到一个数据库。一个依赖于另一个的id,但是我不能获取id,直到我已经将其插入到数据库中并获得结果。除此之外,第一个插入依赖于数据库中的查询。数据库调用返回承诺,用于将两个调用链接到一个序列中。

  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失败,它会调用err函数首先是但是,这将成为下一个承诺的成功功能。虽然这个承诺是期望第一个值的结果,但它会从错误处理函数中获取错误消息。



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



对不起,这个长度。我不知道如何用另一种方式解释。



更新和更正



(注意:我删除了我曾经对某些评论发表的回复,所以如果有人对我的回复发表了评论,那么他们的评论可能看起来已经不在上下文,所以我删除了它,对不起,我试图把它保持为尽可能短。)



感谢所有回复的人。我想先向所有人道歉,写出我的问题如此糟糕,特别是我的伪代码。我有点过于激进,试图保持简短。



感谢Bergi的回应,我想我发现我的逻辑错误。我想我可能忽视了另一个导致我遇到的问题的问题。这可能导致承诺链的工作不同于我以为应该。我仍然在测试我的代码的不同元素,所以我甚至不能形成一个正确的问题,看看我做错了什么。我确实想要更新你,谢谢你的帮助。

解决方案


对我来说,这个结果没有意义。通过附加到这个承诺链,每个都意味着它将取决于成功解决d1,并将结果传递给链条


不。你所描述的不是链,而是将所有回调附加到 d1 。但是,如果要链接然后的东西, promise2 的结果取决于 promise1 以及然后回调处理它



文档状态:


为回调结果返回新的承诺。


通常使用承诺/ A规范(或更严格的 Promsises / A + one )。这意味着回调shell返回承诺,将被同化以成为 promise2 的解决方案,如果没有成功/错误处理程序,相应的结果将被直接传递到 promise2 - 所以你可以简单地省略处理程序来传播错误。



,如果错误是被处理,则生成的 promise2 被视为已修复的,并将被满足该值。如果你不想要的话,就像在try-catch子句中一样,你必须 < - c $ c> throw 错误。或者,您可以从处理程序返回(被拒绝)拒绝的承诺。不知道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;},
函数(err){console.log('promise2拒绝'); throw err;});
var promise3 = promise2.then(
function(wins){console.log('promise3 resolved'); return wins;},
function(err){console.log('promise3拒绝'); throw err;});
d1.reject(new Error());




Bob如何能够从Ginger得到一个蓝色的小部件,没有任何自己?


他不应该能够。如果没有错误处理程序,他只会感觉到(来自Ginger的(来自John的)经销商)的消息(没有小部件)。然而,如果Ginger设置了一个错误处理程序,她仍然可以履行她的诺言,给Bob一个小部件,如果John或他的分销商没有蓝色的,那么给自己一个绿色的小屋。 >

要将错误回调转换为元代码,处理程序中的 return err 就像说如果没有小部件剩下的,只是给他留下了没有留下的笔记 - 它与所需的小部件一样好。


在数据库情况下,如果db.query失败,它将调用第一个然后


...的err函数,这将意味着错误在那里处理。如果不这样做,只需省略错误回调。 Btw,你的成功回调不是返回他们正在创建的承诺,所以他们似乎没有用。正确的是:

  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();
});
});
});

或者,由于您不需要关闭来访问先前回调的结果值,甚至: / p>

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


I am have a problem understanding why rejections are not passed on through a promise chain and I am hoping someone will be able to help me understand why. To me, attaching functionality to a chain of promises implies an intent that I am depending on an original promise to be fulfilled. It's hard to explain, so let me show a code example of my problem first. (Note: this example is using Node and the deferred node module. I tested this with Dojo 1.8.3 and had the same results)

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());

The results of running this operation is this output:

promise1 rejected
promise2 resolved
promise3 resolved

Okay, 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. If the promise in promise1 doesn't receive the wins value, but instead gets an err value in its error handler, how is it possible for the next promise in the chain to have its success function called? There is no way it can pass on a meaningful value to the next promise because it didn't get a value itself.

A different way I can describe what I'm thinking is: There are three people, John, Ginger, and Bob. John owns a widget shop. Ginger comes into his shop and requests a bag of widgets of assorted colours. He doesn't have them in stock, so he sends in a request to his distributor to get them shipped to him. In the mean time, he gives Ginger a rain check stating he owes her the bag of widgets. Bob finds out Ginger is getting the widgets and requests that he get the blue widget when she's done with them. She agrees and gives him a note stating she will. Now, John's distributor can't find any widgets in their supply and the manufacturer doesn't make them any more, so they inform John, who in turn informs Ginger she can't get the widgets. How is Bob able to get a blue widget from Ginger when didn't get any herself?

A third more realistic perspective I have on this issue is this. Say I have two values I want updated to a database. One is dependant on the id of the other, but I can't get the id until I have already inserted it into a database and obtained the result. On top of that, the first insert is dependant on a query from the database. The database calls return promises that I use to chain the two calls into a sequence.

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 });

Now, in this situation, if the db.query failed, it would call the err function of the first then. But then it would call the success function of the next promise. While that promise is expecting the results of the first value, it would instead get the error message from its error handler function.

So, my question is, why would I have an error handing function if I have to test for errors in my success function?

Sorry for the length of this. I just didn't know how to explain it another way.

UPDATE and correction

(Note: I removed a response I had once made to some comments. So if anyone commented on my response, their comments might seem out of context now that I removed it. Sorry for this, I am trying to keep this as short as possible.)

Thank you everybody who replied. I would like to first apologize to everybody for writing out my question so poorly, especially my pseudo code. I was a little too aggressive in trying to keep it short.

Thanks to Bergi's response, I think I found the error in my logic. I think I might have overlooked another issue that was causing the problem I was having. This is possibly causing the promise chain work differently than I thought it should. I am still testing different elements of my code, so I can't even form a proper question to see what I'm doing wrong yet. I did want to update you all though and thank you for your help.

解决方案

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

No. What you are describing is not a chain, but just attaching all the callbacks to d1. Yet, if you want to chain something with then, the result for promise2 is dependent on the resolution of promise1 and how the then callbacks handled it.

The docs state:

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

The .then method is usually looked upon in terms of the Promises/A specification (or the even stricter Promsises/A+ one). That means the callbacks shell return promises which will be assimilated to become the resolution of promise2, and if there is no success/error handler the respective result will in case be passed directly to promise2 - so you can simply omit the handler to propagate the error.

Yet, if the error is handled, the resulting promise2 is seen as fixed and will be fulfilled with that value. If you don't want that, you would have to re-throw the error, just like in a try-catch clause. Alternatively you can return a (to-be-)rejected promise from the handler. Not sure what Dojo way to reject is, but:

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?

He should not be able. If there are no error handlers, he will just perceive the message (((from the distributor) from John) from Ginger) that there are no widgets left. Yet, if Ginger sets up an error handler for that case, she still might fulfill her promise to give Bob a widget by giving him a green one from her own shack if there are no blue ones left at John or his distributor.

To translate your error callbacks into the metapher, return err from the handler would just be like saying "if there are no widgets left, just give him the note that there are no ones left - it's as good as the desired widget".

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

…which would mean that the error is handled there. If you don't do that, just omit the error callback. Btw, your success callbacks don't return the promises they are creating, so they seem to be quite useless. Correct would be:

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();
        });
    });
});

or, since you don't need the closures to access result values from previous callbacks, even:

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);

这篇关于链接的承诺不会被拒绝的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆