从JS中被拒绝的承诺中恢复 [英] Recovering from rejected promises in JS

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

问题描述

我正在使用本机承诺(主要是)并尝试从错误中恢复并继续执行承诺链。



实际上,我这样做:




  • 查询是否存在ID的REST查询。 请注意,这会返回延迟的jquery。

  • .then(成功意味着ID存在,因此失败并停止)
    (失败意味着ID不存在) ,继续创建ID)

  • .then(创建ID记录并发送到服务器)



我从被拒绝的函数返回一个Promise.resolve(),它应该导致下一个.then的成功部分执行。它不是。我在Chrome和Safari上试过这个。



请注意,第一个承诺实际上是延迟查询,但根据此页面( http://api.jquery.com/deferred.then/ ),deferred.then()返回一个promise对象。所以添加一个额外的.then应该转换为原生承诺。



为了更清楚 - 这里是伪代码:

  promise = $ .ajax(url); 
promise = promise.then(); //转换为promise
promise.then(function(){cleanup();返回Promise.reject();},
function(err){return Promise.resolve();});
.then(function(){createIdentityDetails();});
.then(function(){sendIdentityDetails();});

请注意,当ajax返回成功时我想失败,我想要
继续当ajax调用失败时进行处理。



所发生的是所有后续.then部分的FAIL函数执行。也就是说,我的返回Promise.resolve()不起作用 - 这是(我认为)违反规范。



我很感激有关如何反馈的任何反馈我可以处理长期承诺链中的错误并从中恢复。



非常感谢您提供的任何建议。



PS创建和收集完整的身份信息非常耗时,因此如果ID存在,我不想这样做。因此我想先检查并快速失败。



pps我真的很喜欢promises解开这些深度嵌套的异步回调链的方式。


假设 createIdentityDetails() sendIdentityDetails()承诺 - 返回异步函数...



如果我们在问题中看到的是整个promise链,那么处理错误条件很简单。没有必要将成功转化为失败或失败转化为成功,或从一种承诺转变为另一种承诺。

  $。ajax(url).then(function(){
cleanup();
} ,function(err){
createIdentityDetails()
.then(sendIdentityDetails);
});

无论 createIdentityDetails()返回的承诺类型如何,这都有效/ code> jQuery或非jQuery。



但是,如果有更多内容,例如调用函数需要被告知结果,那么你需要做更多,这取决于您希望如何报告可能的结果。



报告'ID已存在'为失败并且'新ID已创建'成功



这就是问题所暗示的

  function foo(){
返回$ .ajax(url).then(function(){
cleanup();
返回$ .Deferred() .reject('失败:ID已存在');
},函数(错误){
返回createIdentityDetails()
.then(sendIdentityDetails)
.then(function() {
返回$ .when('成功:创建新ID');
});
});
}

将两种类型的结果报告为成功



这似乎更明智,因为处理错误将被报告为成功。只会报告不可预测的未处理错误。

  function foo(){
return $ .ajax(url).then(function(){
cleanup();
返回'成功:ID已存在';
},函数(错误){
返回createIdentityDetails ()
.then(sendIdentityDetails)
.then(function(){
return $ .when('success:new id created');
});
});
}

无论采用哪种报告策略,重要的是什么类型的承诺 createIdentityDetails()返回。作为链中的第一个承诺,它决定了它的链式.thens的行为。




  • 如果 createIdentityDetails()返回本机ES6承诺,那么不用担心,大多数承诺的味道,甚至是jQuery,都会被同化。

  • 如果 createIdentityDetails()返回一个jQuery承诺,那么只有jQuery promises将是同化。因此 sendIdentityDetails()还必须返回一个jQuery承诺(或者必须使用 $重新转换为jQuery的ES6承诺。延期(...)),最后成功转换器必须(如上所示)。



你可以看到混合效果jQuery和ES6以这两种方式承诺此处。第一个警报由第二个代码块生成,而不是预期的。第二个警报由第一个块生成,并正确地给出结果98 + 1 + 1 = 100.


I'm using native promises (mostly) and attempting to recover from an error and continue executing the promise chain.

Effectively, I'm doing this:

  • REST query to see if ID exists. Note that this returns a jquery deferred.
  • .then (success means ID exists, so fail and stop) (fail means ID does not exist, so continue creating ID)
  • .then (create the ID record and send to the server)

I return a Promise.resolve() from my rejected function, which should cause the success part of the next .then to execute. It does not. I've tried this on Chrome and Safari.

Note that the first promise is actually a query deferred, but according to this page (http://api.jquery.com/deferred.then/), deferred.then() returns a promise object. So adding an extra .then should covert to native promises.

To make it clearer - here's the pseudocode:

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

Note that I want to FAIL when the ajax returns success, and I want to continue processing when the ajax call fails.

What happens is that the FAIL functions for all subsequent .then portions execute. That is, my return Promise.resolve() doesn't work - which is (I think) in violation of the spec.

I'd appreciate any feedback on how I can deal with and recover from errors in long promise chains.

Many thanks for any advice you can provide.

p.s. creating and collecting the full identity information is quite time consuming, so I don't want to do it if the ID exists. Hence I want to check first and fail quickly.

p.p.s I really like the way that promises have unwound these deeply nested async callback chains.

解决方案

Assuming createIdentityDetails() and sendIdentityDetails() to be promise-returning asynchronous functions ...

If what we see in the question is the entirety of the promise chain, then handling the error condition is simple. It's not necessary to convert success to failure or failure to success, or from one type of promise to another.

$.ajax(url).then(function() {
    cleanup();
}, function(err) {
    createIdentityDetails()
    .then(sendIdentityDetails);
});

This will work regardless of the type of promise returned by createIdentityDetails() jQuery or non-jQuery.

If, however, there's more to it, eg a caller function needs to be informed of the outcome, then you need to do more, and it depends on how you want the possible outcomes to be reported.

Report 'ID already exists' as failure and 'new ID created' as success

This is what the question suggests

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

Report both types of outcome as success

This seems more sensible as the handled error will be reported as success. Only unpredicted, unhandled errors will be reported as such.

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

Whichever reporting strategy is adopted, it matters very much what type of promise createIdentityDetails() returns. As the first promise in the chain it determines the behaviour of both its chained .thens.

  • if createIdentityDetails() returns a native ES6 promise, then no worries, most flavours of promise, even jQuery, will be assimilated.
  • if createIdentityDetails() returns a jQuery promise, then only jQuery promises will be assimilated. Therefore sendIdentityDetails() must also return a jQuery promise (or an ES6 promise which must be recast into jQuery with $.Deferred(...)), as must the final success converter (as coded above).

You can see the effects of mixing jQuery and ES6 promises in these two ways here. The first alert is generated by the second block of code, and is not what is expected. The second alert is generated by the first block and correctly gives the result 98 + 1 + 1 = 100.

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

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