小编典典

链接两个异步jQuery函数时,如何完全避开jQuery Promise?

javascript

我已经看过许多有关新EMCA的教程,这些教程承诺提倡在jQuery库中避免“承诺”。他们通常说您可以通过执行以下操作来躲避他们:

Promise.resolve($.getJSON(url, params)); // voila!  the jQuery promise is "gone"!

但是,当我必须将两个异步jQuery函数链接在一起时,这实际上不起作用。我如何将两个getJSON调用(第二个调用取决于第一个调用)链接在一起而不使用jQuery的then()或.when()?

相反,我只想使用Promise.all等。

我认为类似的问题是交错jquery和EMCA Promise?


阅读 314

收藏
2020-04-25

共1个答案

小编典典

您可以采用两种方法之一…

转换然后合并:

var p1 = Promise.resolve($.getJSON(url_1, params_1)); // voila 1!
var p2 = Promise.resolve($.getJSON(url_2, params_2)); // voila 2!
var p3 = Promise.all([p1, p2]).then(...);

合并然后转换:

var p1 = $.getJSON(url_1, params_1);
var p2 = $.getJSON(url_2, params_2);
var p3 = Promise.resolve($.when(p1, p2)).then(...); // voila 1 and 2!

直截了当,两种方法都将为您提供本机的ES6 Promise,p3当两个jQuery Promise
都解决时,它就会解决;当其中一个Promise失败时,它就会被拒绝。

但是,您可能对这两个getJSON()调用的结果感兴趣,并且jQuery在这方面很尴尬。jQuery的jqXHR Promise将 多个
参数传递给它们的成功和错误回调,而ES6
Promise只接受一个。其余的将被忽略。幸运的是,将多个参数捆绑在一起以创建单个对象非常简单。必须先在jQuery中完成,然后再转换为ES6。

“转换然后合并”代码扩展如下:

var p1 = Promise.resolve($.getJSON(url_1, params_1).then(
    function(data, textStatus, jqXHR) {
        return { data:data, textStatus:textStatus, jqXHR:jqXHR };
    },
    function(jqXHR, textStatus, errorThrown) {
        return { jqXHR:jqXHR, textStatus:textStatus, errorThrown:errorThrown };
    }
));
var p2 = Promise.resolve($.getJSON(url_2, params_2).then(
    function(data, textStatus, jqXHR) {
        return { data:data, textStatus:textStatus, jqXHR:jqXHR };
    },
    function(jqXHR, textStatus, errorThrown) {
        return { errorThrown:errorThrown, textStatus:textStatus, jqXHR:jqXHR };
    }
));
var p3 = Promise.all([p1, p2]).then(
    function(results) {
        // results[0] will be an object with properties .data, .textStatus, .jqXHR 
        // results[1] will be an object with properties .data, .textStatus, .jqXHR 
    },
    function(rejectVal) {
        // rejectVal will be an object with properties .errorThrown, .textStatus, .jqXHR
    }
);

“合并然后转换”方法比较棘手,因为合并的结果(在jQuery中)显示为arguments列表,列表本身需要转换(仍在jQuery中)为数组。

var p1 = $.getJSON(url_1, params_1).then(
    function(data, textStatus, jqXHR) { 
        return { data:data, textStatus:textStatus, jqXHR:jqXHR }; 
    },
    function(jqXHR, textStatus, errorThrown) { 
        return { errorThrown:errorThrown, textStatus:textStatus, jqXHR:jqXHR }; 
    }
);
var p2 = $.getJSON(url_2, params_2).then(
    function(data, textStatus, jqXHR) { 
        return { data:data, textStatus:textStatus, jqXHR:jqXHR };
    },
    function(jqXHR, textStatus, errorThrown) { 
        return { errorThrown:errorThrown, textStatus:textStatus, jqXHR:jqXHR }; 
    }
);
var p3 = Promise.resolve($.when(p1, p2).then(function() {
    return [].slice.call(arguments);// <<< convert arguments list to Array
})).then(
    function(results) { 
        // results[0] will be an object with properties .data, .textStatus, .jqXHR
        // results[1] will be an object with properties .data, .textStatus, .jqXHR
    },
    function(rejectVal) { 
        // rejectVal will be an object with properties .errorThrown, .textStatus, .jqXHR
    }
);
2020-04-25