【问题标题】:Mixing ES6 Promises with JQuery Promises将 ES6 Promise 与 JQuery Promise 混合使用
【发布时间】:2016-07-15 07:40:01
【问题描述】:

我使用过 $q (Angular.js) 并且经常会在 .then 调用中返回承诺。结果是下一个.then 调用将等待前一个promise 完成。

我现在正在使用本机 es6 承诺尝试“承诺”基于回调的库,但我无法这样做。

问题在于.then 链中的下一个值是一个promise 对象,而不是该promise 的已解决值。它在 promise 被解析之前调用下一个 .then 值,只是返回最后一个返回值。

还有没有等待之前的promise解决?

例子:

$.ajax({
    url: "//localhost:3000/api/tokens",
    type: "POST",
    data: JSON.stringify({
      user: {
        email: 'admin@admin.com',
        password: 'password123'
      }
    }),
    contentType: "application/json"
})
.then(data => data.token.encoded)         // OK
.then(token => Farmbot({ token: token })) // OK
.then(function(bot){                      // OK
  return new Promise(function(resolve, reject) {
    bot.connect(function(){ resolve(bot); });
  });
}, errorr)
.then(function(bot){ // NOT OK!
  // passes in an unresolved promise object, which is useless.
  //
  bot; // => {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
});

我的问题是:

ES6 Promise 会等待之前的 .then 的 Promise 解决吗?

【问题讨论】:

  • Angular 和 jQuery 并不是特别好的伙伴。在 Angular 应用程序中,您应该真正使用 $http(),而不是 jQuery.ajax()

标签: javascript jquery angularjs promise ecmascript-6


【解决方案1】:

问题源于尝试在Deferred promises 链中使用本机Promise

目前(jQuery 1.8 – 2.x),jQuery 对.then() 的定义仅识别库自身的类型以支持链接。

因此,您可以改为返回 $.Deferred() 承诺:

// ...
.then(function(bot){
  return $.Deferred(function(defer) {
    bot.connect(function(){ defer.resolve(bot); });
  });
}, errorr)
// ...

或者,您可以使用Promise.resolve(thenable)$.ajax() 给出的初始$.Deferred() 转换为本机Promise,以便您在整个链中使用本机.then(),它将识别@987654341 @ 被返回(以及$.Deferred()):

Promise.resolve($.ajax({
  // ...
}))
.then(data => data.token.encoded)
// ...

或者,你可以试试 jQuery 3.0,currently in beta:

jQuery.Deferred 现在兼容 Promises/A+

jQuery.Deferred 对象已更新以兼容 Promises/A+ 和 ES2015 Promises,并通过 Promises/A+ Compliance Test Suite 进行了验证。 [...]

有了它,您原来的 sn-p 应该可以按预期工作,无需任何修改。

【讨论】:

  • 在第二个代码中,.then(() => req) 会起作用吗?我的意思是req 仍然是 jquery 的类型....
  • @RoyiNamir 原生 .then() 将返回一个 new Promise(),并且该方法被定义为与其他“thenables”一起使用,例如 Deferreds。
  • 好吧,发现多余的.then() 并不是真正需要的。 Promise.resolve(thenable) 覆盖它。但是,是的,它似乎适用于 3.0-beta1 (jsfiddle.net/694o4x32) 和 2.2.2 (jsfiddle.net/kuLbh12a)。
【解决方案2】:

ES6 的 Promise 会等待前一个 .then 的 Promise 解决吗?

这样说:一个 ES6 承诺永远不会使用一个承诺或 thenable 对象调用 .then(onFulfilled) 函数。仅使用非承诺值调用 Onfulfilled 侦听器。

在信任之前将 jQuery "thenable" 对象转换为 ES6 Promise 可能会解决问题:

var jqPromise = $.ajax({
    url: "//localhost:3000/api/tokens",
    type: "POST",
    data: JSON.stringify({
      user: {
        email: 'admin@admin.com',
        password: 'password123'
      }
    }),
    contentType: "application/json"
})
.then(data => data.token.encoded)         // OK
.then(token => Farmbot({ token: token })) // OK

; 

var es6Promise = Promise.resolve(jqPromise); // convert to ES6 promise

es6Promise.then(function(bot){                      // OK
  return new Promise(function(resolve, reject) {
    bot.connect(function(){ resolve(bot); });
  });
}, errorr)
.then(function(bot){ // will not pass in unfulfilled promise

  // process bot value

});

【讨论】:

    猜你喜欢
    • 2016-05-09
    • 2020-02-02
    • 2018-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多