链接两个异步 jQuery 函数时如何完全避开 jQuery 承诺?
How to dodge jQuery promises completely when chaining two async jQuery functions?
我看过许多关于新 EMCA 承诺的教程,这些教程提倡避免 jQuery 库中的 "promises"。他们通常说你可以通过这样做来躲避他们:
Promise.resolve($.getJSON(url, params)); // voila! the jQuery promise is "gone"!
但是,当我必须将两个异步 jQuery 函数链接在一起时,这实际上不起作用。我如何在不使用 jQuery 的 then() 或 .when() 的情况下将两个 getJSON 调用(第二个调用取决于第一个)链接在一起?
相反,我只想使用 Promise.all 等
我认为类似的问题会交错 jquery 和 EMCA 承诺?
JavaScript 承诺是 interoperable。您可以根据需要混合使用它们,所有适当的库1 和本机承诺都接受来自任何实现的 thenables2 anywhere3。如果出现异物,他们就会Promise.resolve
处理它。
所以通常你会编写你的代码,就好像它们都使用相同的承诺实现一样,而且它 正常工作。
但是,现在您要确保所有 .then
方法调用都使用您最喜欢的实现;或者您想使用非标准方法或功能?为此,您将必须显式地投射您正在直接调用方法的所有承诺 - 仅此而已。
一些例子:
Promise.all([$.ajax(…), $.ajax(…)]).then(…); // just works!
$.ajax(…) // a jQuery promise
<s>.then(…)</s> // 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:是的,jQuery 在 3.0
版本之前不是其中之一
2:所有 jQuery 延迟和承诺都是这样的 thenables,尽管
3:真的处处你会期待一个承诺,在Promise.resolve
,then
回调return值,Promise.all
参数,...
您可以采用两种方法中的任何一种...
转换然后合并:
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 承诺将只接受一个;剩下的会
被忽视。幸运的是,将多个参数捆绑在一起以创建单个对象相当简单。这必须在 jQuery 转换为 ES6 之前完成。
"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
}
);
"combine then convert" 方法稍微有点棘手,因为组合结果(在 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
}
);
我看过许多关于新 EMCA 承诺的教程,这些教程提倡避免 jQuery 库中的 "promises"。他们通常说你可以通过这样做来躲避他们:
Promise.resolve($.getJSON(url, params)); // voila! the jQuery promise is "gone"!
但是,当我必须将两个异步 jQuery 函数链接在一起时,这实际上不起作用。我如何在不使用 jQuery 的 then() 或 .when() 的情况下将两个 getJSON 调用(第二个调用取决于第一个)链接在一起?
相反,我只想使用 Promise.all 等
我认为类似的问题会交错 jquery 和 EMCA 承诺?
JavaScript 承诺是 interoperable。您可以根据需要混合使用它们,所有适当的库1 和本机承诺都接受来自任何实现的 thenables2 anywhere3。如果出现异物,他们就会Promise.resolve
处理它。
所以通常你会编写你的代码,就好像它们都使用相同的承诺实现一样,而且它 正常工作。
但是,现在您要确保所有 .then
方法调用都使用您最喜欢的实现;或者您想使用非标准方法或功能?为此,您将必须显式地投射您正在直接调用方法的所有承诺 - 仅此而已。
一些例子:
Promise.all([$.ajax(…), $.ajax(…)]).then(…); // just works!
$.ajax(…) // a jQuery promise
<s>.then(…)</s> // 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:是的,jQuery 在 3.0
版本之前不是其中之一
2:所有 jQuery 延迟和承诺都是这样的 thenables,尽管
3:真的处处你会期待一个承诺,在Promise.resolve
,then
回调return值,Promise.all
参数,...
您可以采用两种方法中的任何一种...
转换然后合并:
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 承诺将只接受一个;剩下的会
被忽视。幸运的是,将多个参数捆绑在一起以创建单个对象相当简单。这必须在 jQuery 转换为 ES6 之前完成。
"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
}
);
"combine then convert" 方法稍微有点棘手,因为组合结果(在 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
}
);