奇怪/意外的jQuery Promise拒绝行为 [英] Strange/unexpected jQuery promise reject behaviour

查看:132
本文介绍了奇怪/意外的jQuery Promise拒绝行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用jQuery拒绝拒绝一些奇怪的行为. 我有很多承诺,当所有承诺都已解决/被拒绝时,我需要与他们合作.

I am experimenting some strange behaviours with jQuery promises on reject. I have an array of promises, and I need to work with them when they all have been resolved/rejected.

为此,我正在使用:

var array_res = [];
array_res.push(promiseResolve('a'));
array_res.push(promiseReject('b'));

$.when.apply(null,array_res).always( function ( ) {
  console.log(arguments);
  //Work to do
} );

function promiseResolve (c) {
  var promise = $.Deferred();
  promise.resolve({a:c});
  return promise;
}

function promiseReject (c) {
  var promise = $.Deferred();
  promise.reject({b:c});
  return promise;
}

问题是:

如果我同时履行两个诺言,一切都会很好.

If I resolve both promises, everything works fine.

如果我拒绝其中一项承诺,那么争论就不完整了.

If I reject one of the promises, then the arguments come incomplete.

如果我拒绝他们两个,那么论点就不完整了.

If I reject both of them, then the arguments come incomplete.

这里有3个小提琴,您可以在其中检查行为:

Here are 3 fiddles where you can check the behaviour:

https://jsfiddle.net/daepqzv1/1/

https://jsfiddle.net/daepqzv1/2/

https://jsfiddle.net/daepqzv1/3/

我需要的是一种获取被拒绝和解决的参数的方法.

What I need is a way to get the arguments for both, rejected and resolved.

推荐答案

这是$.when()的正常行为.如果您传递给$.when()的任何拒绝请求,则$.when()将拒绝它并找到它的第一个拒绝原因.这就是它的编码方式.

This is normal behavior for $.when(). If any promises you pass to $.when() reject, then $.when() will reject with the first reject reason that it finds. This is how it is coded.

这类似于ES6 Promise.all()的工作方式.

This is similar to the way the ES6 Promise.all() works.

如果您希望获得所有结果,即使某些承诺被拒绝,也可以使用此代码中定义的类似$.settle()$.settleVal()的内容:

If you want all results, even if some promises reject, then you can use something like $.settle() or $.settleVal() that are defined in this code:

(function() {    

    function isPromise(p) {
        return p && (typeof p === "object" || typeof p === "function") && typeof p.then === "function";
    }

    function wrapInPromise(p) {
        if (!isPromise(p)) {
            p = $.Deferred().resolve(p);
        }
        return p;
    }

    function PromiseInspection(fulfilled, val) {
        return {
            isFulfilled: function() {
                return fulfilled;
            }, isRejected: function() {
                return !fulfilled;
            }, isPending: function() {
                // PromiseInspection objects created here are never pending
                return false;
            }, value: function() {
                if (!fulfilled) {
                    throw new Error("Can't call .value() on a promise that is not fulfilled");
                }
                return val;
            }, reason: function() {
                if (fulfilled) {
                    throw new Error("Can't call .reason() on a promise that is fulfilled");
                }
                return val;
            }
        };
    }

    // pass either multiple promises as separate arguments or an array of promises
    $.settle = function(p1) {
        var args;
        if (Array.isArray(p1)) {
              args = p1;
        } else {
            args = Array.prototype.slice.call(arguments);
        }

        return $.when.apply($, args.map(function(p) {
            // make sure p is a promise (it could be just a value)
            p = wrapInPromise(p);
            // Now we know for sure that p is a promise
            // Make sure that the returned promise here is always resolved with a PromiseInspection object, never rejected
            return p.then(function(val) {
                return new PromiseInspection(true, val);
            }, function(reason) {
                // convert rejected promise into resolved promise by returning a resolved promised
                // One could just return the promiseInspection object directly if jQuery was
                // Promise spec compliant, but jQuery 1.x and 2.x are not so we have to take this extra step
                return wrapInPromise(new PromiseInspection(false, reason));
            });
        })).then(function() {
              // return an array of results which is just more convenient to work with
              // than the separate arguments that $.when() would normally return
            return Array.prototype.slice.call(arguments);
        });
    }

    // simpler version that just converts any failed promises
    // to a resolved value of what is passed in, so the caller can just skip
    // any of those values in the returned values array
    // Typically, the caller would pass in null or 0 or an empty object
    $.settleVal = function(errorVal, p1) {
        var args;
        if (Array.isArray(p1)) {
              args = p1;
        } else {
            args = Array.prototype.slice.call(arguments, 1);
        }
        return $.when.apply($, args.map(function(p) {
            p = wrapInPromise(p);
            return p.then(null, function(err) {
                return wrapInPromise(errorVal);
            });
        }));
    }
})();

$.settle()始终会解析,并使用PromiseInspection对象数组来解析,然后您可以对其进行迭代以查看哪些承诺已解决,哪些承诺被拒绝以及价值或原因是什么.

$.settle() always resolves and it resolves with an array of PromiseInspection objects that you can then iterate over to see which promises resolved and which rejected and what the value or reason was.

$.settleVal()的迭代更简单一些,但通用性却稍差一些,因为它没有给您拒绝的理由.它总是使用数组来解析,其中拒绝将具有您在数组中传递给它的默认值,而不是解析值.

$.settleVal() is a little simpler to iterate, but a little less generic because it doesn't give you the reject reason. It always resolves with an array where a reject will have a default value that you pass to it in the array in place of the resolved value.

仅供参考,$.settle()$.settleVal()都可以传递诸如$.settle(arrayOfPromises)之类的诺言数组或作为$.settle(p1, p2, p3)的多个诺言参数(随着$.when()工作).当您有多个诺言时,这样就不必使用.apply().

FYI, both $.settle() and $.settleVal() can both be passed an array of promises like $.settle(arrayOfPromises) or multiple promise arguments as $.settle(p1, p2, p3) (as $.when() works). This saves having to use .apply() when you have an array of promises.

这篇关于奇怪/意外的jQuery Promise拒绝行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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