为了账号安全,请及时绑定邮箱和手机立即绑定

$ .Deferred:如何检测每个承诺何时执行

$ .Deferred:如何检测每个承诺何时执行

蝴蝶不菲 2019-09-06 15:57:57
我有许多需要完成的异步任务,所以我使用的是promises。我需要检测每个承诺何时被执行(解决和拒绝)。在此之前我不能继续执行。我使用的是这样的东西:$.when(promise1, promise2, ...).always();但是这个代码是错误的,因为该when方法具有惰性求值,并且只要其中一个promise失败就会返回。因此,always只要其中一个承诺失败,回调也会运行。我想在编码一个解决办法,但这种使用情况是如此普遍,也许有人已经做它已经,或者也许甚至还有这样做只使用jQuery的的一种方式(如果不是,这将是很好添加Promise.whenNonLazy或Promise.when(promise1, promise2, ..., false)在未来。这可能吗?
查看完整描述

3 回答

?
函数式编程

TA贡献1807条经验 获得超9个赞

更复杂的诺言库有一个allSettled()类似的功能Q或Promise.settle类似蓝鸟。


在jQuery中,您也可以自己实现这样的函数并$使用它扩展命名空间,但只有在经常需要它并进行性能优化时才需要这样做。


一个更简单的解决方案是为你正在等待的每一个创建一个新的承诺,并且即使当底层的一个被拒绝时也要实现它们。然后你可以$.when()毫无问题地使用它们。简而言之:


// using Underscore's .invoke() method:

$.when.apply(null, _.invoke(promises, "then", null, $.when)).done(…)

更稳定:


$.when.apply($, $.map(promises, function(p) {

    return p.then(null, function() {

        return $.Deferred().resolveWith(this, arguments);

    });

})).then(…);

您可以then稍微更改回调以区分最终的已完成和已拒绝的结果done。


查看完整回答
反对 回复 2019-09-06
?
千巷猫影

TA贡献1829条经验 获得超7个赞

铁匠铺,


首先让我们假设你的承诺是一个数组。


var promises = [....];

您似乎想要的是.when()应用于这些承诺的某些转换,这样任何被拒绝的承诺都会转换为已解决,同时对已经解决的承诺透明。


所需的操作可以非常简洁地写成如下:


$.when.apply(null, $.map(promises, resolvize)).done(...);

//or, if further filtering by .then() is required ...

$.when.apply(null, $.map(promises, resolvize)).then(...);

resolvize转换机制在哪里。


那应该resolvize()怎么样?让我们利用特征.then()来区分已解决和被拒绝的承诺,并做出相应的响应。


function resolvize(promise) {

    //Note: null allows a resolved promise to pass straight through unmolested;

    return promise.then(null, function() {

        return $.Deferred().resolve.apply(null, arguments).promise();

    });

}

未经测试


与resolvize在某些外部范围,它可以被提供给被用在$.when.apply($.map(promises, resolvize))任何需要它的表达。这很可能是足够的,没有达到用新方法扩展jQuery的程度。


无论转变如何实现,您最终都会遇到潜在的问题; 即知道.done()回调的每个参数,是否最初解决或拒绝其相应的承诺。这是您将拒绝转换为解决方案所付出的代价。但是,您可以从原始承诺被解决/拒绝的参数中检测原始状态。


查看完整回答
反对 回复 2019-09-06
  • 3 回答
  • 0 关注
  • 426 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信