以下Promise
按预期行事,Promise
语句中的return
得到满足,之后then
在最后一次调用之前执行:
(new Promise(resolve => resolve(true)))
.then(function(){
console.log(0);
return new Promise(resolve => setTimeout(resolve, 1000))
.then(function() {
console.log(1);
});
}).then(function() {
console.log(2);
});
结果是
0
1
2
但是当第一个Promise
是jQuery Promise
时,如下例所示
$.post("index.php")
.then(function() {
console.log(0);
return new Promise(resolve => setTimeout(resolve, 1000))
.then(function() {
console.log(1);
});
}).then(function() {
console.log(2);
});
结果是
0 2 1
表示第二个Promise
未按照标准JavaScript承诺传递
有没有办法强制标准行为?
我正在使用jQuery 2.0.0。
答案 0 :(得分:5)
jQuery 2不支持Promises/A+,也无法吸收其他实现的承诺(" thenables")。从回调中返回并解析外部承诺的本机承诺不会被等待,而是用作立即履行值。您可以通过检查传递给最终回调的参数来看到这一点。
有没有办法强制标准行为?
请参阅How to dodge jQuery promises completely when chaining two async jQuery functions?
基本上只需在$.post("index.php")
中包含启动链的Promise.resolve
即可获得具有所有荣耀(以及预期行为)的原生承诺。
反之亦然(在jQuery承诺中包含超时的本机承诺)我真的不推荐,但它基本上归结为
return $.Deferred(def => promise.then(def.resolve, def.reject)).promise()
答案 1 :(得分:1)
jQuery(你使用的版本)可能不适用于es6 promises,我认为它们可以使用称为“延迟对象”的东西,因为它不起作用。
伟大的凯尔辛普森在他的书“你不知道Js:Async and performance”中写下了承诺,这可以帮助你:
“从ES6开始,在事件循环队列之上有一个新概念,称为”作业队列“。最可能的暴露是Promise的异步行为(参见第3章) 。“
由于“新概念分层”,你的jquery版本不可能很好地将“假”承诺与标准承诺混合在一起。
尝试使用以下内容覆盖$ .post:
Promise.resolve($.post("index.php"))
.then(function() {
console.log(0);
return new Promise(resolve => setTimeout(resolve, 1000))
.then(function() {
console.log(1);
});
}).then(function() {
console.log(2);
});
现在你的承诺链都是es6标准。
Kyle Simpson书的链接:
You Don't Know JS: Async & Performance
链接可以看到所有你不知道的JS系列书: