如何在链接两个asynchronousjQuery函数时完全避开jQuery承诺?

我已经看到许多关于新的EMCA承诺的教程,主张避免jQuery库中的“承诺”。 他们通常说你可以通过做这样的事情来躲避他们:

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

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

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

我认为类似的问题会交错jquery和EMCA的承诺?

你可以采取两种办法之一…

转换然后结合:

 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承诺, p3 ,它可以解决jQuery承诺解决的问题,或者当任何一个承诺失败时都被拒绝。

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

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

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

DEMO:已解决

DEMO:拒绝

JavaScript承诺是可互操作的 。 你可以把它们混合起来,但是所有合适的库1和本地的promise都可以接受来自任何地方 3的实现。 如果有外国人出现,他们只会做Promise.resolve就可以了。

所以通常你会编写你的代码,就好像它们都使用了相同的promise实现,而且它是正常的
但是,现在您要确保所有.then方法调用正在使用您最喜欢的实现; 或者你想使用一个非标准的方法或function? 为此,您将不得不明确地施放直接调用方法的 所有承诺 – 而不是别的。

一些例子:

 Promise.all([$.ajax(…), $.ajax(…)]).then(…); // just works! 
 $.ajax(…) // a jQuery promise .then(…) // so this would be jQuery `then`, which we don't want. 
 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 

1:是的,在3.0版之前,jQuery不是其中之一
2: 尽pipe如此 ,所有的jQuery延期和承诺都是如此
3:真的无处不在你期望的承诺, Promise.resolvethencallback返回值, Promise.all参数,…