我使用过$ q(Angular.js)并经常在.then
调用中返回promises。结果是下一个.then
调用将等待先前的承诺完成。
我现在正在使用本机es6承诺尝试“宣传”##一个基于回调的库,我无法这样做。
问题是.then
链中的下一个值是 promise对象,而不是该promise的已解析值。它在解析promise之前调用下一个.then
值,只返回最后一个返回值。
有没有等待先前的承诺解决?
示例:
$.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承诺会等待之前.then
的承诺解决吗?
答案 0 :(得分:22)
问题源于尝试在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)
将$.Deferred()
提供的初始$.ajax()
转换为原生Promise
,以便您使用原生.then()
在整个链中,它将识别返回的new Promise()
(以及$.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进行验证。 [...]
有了它,您的原始代码段应该按预期工作而不进行任何修订。
答案 1 :(得分:3)
ES6承诺是否等待之前的.then承诺解决?
这样说:ES6承诺永远不会使用promise或者then对象调用.then(onFulfilled)
函数。仅使用非承诺值调用Onfulfilled侦听器。
在信任它们之前将jQuery“thenable”对象转换为ES6 Promises可以解决问题:
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
});