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

use*_*094 5 javascript jquery promise es6-promise

我见过很多关于新EMCA承诺的教程,主张避免jQuery库中的"promises".他们通常说你可以通过做这样的事情来躲避他们:

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

但是,当我必须将两个异步jQuery函数链接在一起时,这并不真正起作用.如何在不使用jQuery的then()或.when()的情况下将两个getJSON调用(第二个调用依赖于第一个调用)链接在一起?

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

我认为一个类似的问题问题是交叉jquery和EMCA的承诺?

Ber*_*rgi 7

JavaScript承诺是可互操作的.您可以根据需要混合使用它们,所有适当的库1和本机承诺都可以接受来自任何地方3的任何实现的thenables 2.如果出现异物,他们就会做.Promise.resolve

所以通常你会编写你的代码,好像它们都使用了相同的promise实现,它只是起作用.
但是,现在您要确保所有.then方法调用都使用您喜欢的实现; 或者您想使用非标准方法或功能?对于这一点,你必须明确地投下所有的承诺在其上直接调用方法 -而不是其他.

一些例子:

Promise.all([$.ajax(…), $.ajax(…)]).then(…); // just works!
Run Code Online (Sandbox Code Playgroud)
$.ajax(…) // a jQuery promise
.then(…)  // so this would be jQuery `then`, which we don't want.
Run Code Online (Sandbox Code Playgroud)
Promise.resolve($.ajax(…)) // explicit cast
.then(function(data) {     // native `then`
    return $.ajax(…);      //   just works!
})                         // returns a native promise still
.catch(…)                  // so we can use its features
Run Code Online (Sandbox Code Playgroud)

1:是的,jQuery是直到3.0版本其中一个
2:所有的jQuery deferreds和承诺是这样thenables,虽然
3:真的无处不在你所期望的一个承诺,在Promise.resolve,then回调的返回值,Promise.all参数,...

  • 请注意,其中一个_goals_ of Promises/A +与jQuery promises兼容,你可以将jQuery"promises"返回到Promises/A +然后它会正确地使用它们.正如你所指出的那样,另一个方向仅来自3.0.可能有用的是说从一个`then`链返回一个值,或者将值传递给聚合方法如`.all`等等是_Implicit的Promise.resolve`_ .. (2认同)

Roa*_*888 5

你可以采用两种方法中的任何一种......

转换然后结合:

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(...);
Run Code Online (Sandbox Code Playgroud)

合并然后转换:

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!
Run Code Online (Sandbox Code Playgroud)

直截了当,任何一种方法都会给你一个原生的ES6承诺,p3当jQuery promises解决时解析,或者当其中一个promise失败时被拒绝.

但是,您可能对这两个getJSON()调用的结果感兴趣,并且jQuery在这方面很尴尬.jQuery的jqXHR承诺将多个参数传递给它们的成功和错误回调,而ES6承诺只接受一个; 其余的将被忽视.幸运的是,将多个参数捆绑在一起以制作单个对象相当简单.这必须在转换到ES6之前在jQuery中完成.

"convert then combine"代码扩展如下:

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
    }
);
Run Code Online (Sandbox Code Playgroud)

"组合然后转换"方法稍微复杂一些,因为组合结果(在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
    }
);
Run Code Online (Sandbox Code Playgroud)

演示:解决了

DEMO:被拒绝了