jQuery promise执行顺序与javascript promise不同

时间:2018-02-10 16:38:55

标签: javascript jquery promise

以下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。

2 个答案:

答案 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系列书:

You Don't Know JS