我已经看到了新的EMCA承诺崇尚jQuery库的“承诺”避免很多教程。 他们通常会说,你可以做这样的事情躲避它们:
Promise.resolve($.getJSON(url, params)); // voila! the jQuery promise is "gone"!
然而,这并不能真正当我必须链上的两个异步的jQuery功能一起工作。 我将如何链上的两个电话的getJSON一起(其中第二呼叫的方式取决于第一),而无需使用jQuery的则()或。当()?
相反,我只是想用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诺言多个参数传递给他们的成功和错误回调,而一个ES6承诺将接受只有一个; 其余的将被忽略。 幸运的是,这是相当简单的多PARAMS捆绑在一起,使一个单一的对象。 这有可能在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
}
);
DEMO:解决
DEMO:拒绝
JavaScript promises are interoperable. You can mix them however you want, all proper libraries1 and native promises do accept thenables2 from any implementation anywhere3. If something foreign appears, they just will do Promise.resolve
on it.
So usually you would write your code as if they all used the same promise implementation, and it just works.
However, now you want to ensure that all .then
method calls are using your favourite implementation; or you want to use a non-standard method or feature? For that, you will have to explicitly cast all promises on which you are directly invoking methods - and nothing else.
Some examples:
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: Yeah, jQuery isn't one of them until version 3.0
2: all jQuery deferreds and promises are such thenables, though
3: Really everywhere you'd expect a promise, in Promise.resolve
, then
callback return values, Promise.all
arguments, …
文章来源: How to dodge jQuery promises completely when chaining two async jQuery functions?