使用jquery时,多个ajax请求$

使用jquery时,多个ajax请求$,jquery,ajax,jquery-deferred,Jquery,Ajax,Jquery Deferred,在jquery上为不同的ajax使用$.when有一些缺点。成功处理ajax调用非常好。但是,如果一个请求失败,您将无法在另一个请求中获取其他数据 前 var ajax1Success=function(){ 返回$.ajax(…); }; var ajax2Success=function(){ 返回$.ajax(…); }; var ajax3BoundtoFail=函数(){ 返回$.ajax(…); }; $.when(ajax1Succes()、ajax2Success()、ajax3

在jquery上为不同的ajax使用$.when有一些缺点。成功处理ajax调用非常好。但是,如果一个请求失败,您将无法在另一个请求中获取其他数据

var ajax1Success=function(){ 返回$.ajax(…); }; var ajax2Success=function(){ 返回$.ajax(…); }; var ajax3BoundtoFail=函数(){ 返回$.ajax(…); }; $.when(ajax1Succes()、ajax2Success()、ajax3BoundtoFail()).done(函数(a1、a2、a3){ //一切都好 }).fail(函数(){ //不好…ajax3肯定会失败 }); 如何从成功的ajax请求中获取其他数据,有什么好的解决方案吗?

$。when()
具有“fail fast”设计。这意味着第一个承诺失败会导致
$.when()
拒绝,而您只会得到拒绝信息。从jQuery文档:

该方法将在所有 延迟解决,或在其中一个 延期被拒绝

但是,您可以使用不同类型的函数来监视您的承诺组。这种类型的功能通常被称为“结算”,在这里,您等待所有承诺结算,并且您从所有承诺中获得结果,无论这些承诺是得到解决还是被拒绝

下面是我在过去使用过的jQuery promies的实现,您可以这样使用:

$.settle([ajax1Succes(), ajax2Success(), ajax3BoundtoFail()]).then(function(results) {
    // results is an array of PromiseInspection Objects
    // for each of them, you can see if the corresponding promise
    // succeeded with a value or failed with an error
    results.forEach(function(pi, index) {
        if (pi.isFulfilled()) {
            console.log("Promise #" + (index + 1) + " succeeded with result " + pi.value());
        } else {
            console.log("Promise #" + (index + 1) + " failed with reason " + pi.reason());
        }
    });
});
或者,如果不需要确切的错误,可以使用更简单的版本:

$.settleVal(null, [ajax1Succes(), ajax2Success(), ajax3BoundtoFail()]).then(function(results) {
    // results contains the results from all the successful promises
    // any promises that has an error will show null as the result
});
请注意,它们使用的接口更像标准的
Promise.all()
,它们接受一系列承诺并解析为一系列结果,因为这通常更易于在现实世界中使用

下面是实现:

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