我在下面有以下承诺链,它看起来很混乱(每个_create
*函数返回一个承诺):
return new Promise(function (resolve, reject) {
_this.database.transaction(function (t) {
_this._createExternalAccount(payment, t)
.then(function (externalAccount) {
return _this._createExternalTransaction(externalAccount, payment, t)
.then(function (externalTransaction) {
return _this._createAddress(externalAccount, payment, t)
.then(function (address) {
return _this._createTransaction(address, payment, t)
.then(function (transaction) {
return _this._createGatewayTransaction(externalTransaction, transaction, payment, t)
.then(function (gatewayTransaction) {
t.commit();
resolve(bridgePayment);
});
});
});
});
})
.error(function (bridgePayment) {
t.rollback();
reject(bridgePayment);
});
});
我知道我可以使用像all()
和join()
这样的Promise函数,但这些函数似乎同时运行我无法做到的函数,因为持久化到某些表需要来自先前持久表的字段。我希望有一些方法让我做以下的事情,但我似乎无法找到如何:
Promise.all(_this._createExternalAccount(payment, t), _this._createExternalTransaction(externalAccount, payment, t), _this._createAddress(externalAccount, payment, t))
.then(function(externalAccount, externalTransaction, address) {
// do logic
});
答案 0 :(得分:6)
我确切地知道你在问什么但是。
如果您想按顺序运行一系列承诺this answer
重要的是要注意的是它不是一系列的承诺。它是一系列承诺的功能。这是因为承诺会立即执行,因此您无法在需要之前创建承诺。
如果你不想把它们放在数组中,虽然正常情况只是将它们正常链接。
再一次,最简单的方法来制作一堆函数返回承诺。那你就是
var p = firstFunctionThatReturnsAPromise()
.then(secondFunctionThatReturnsAPromise)
.then(thirdFunctionThatReturnsAPromise)
.then(fourthFunctionThatReturnsAPromise)
您可以轻松地嵌套它们
function AOuterFunctionThatReturnsAPromise() {
var p = firstFunctionThatReturnsAPromise()
.then(secondFunctionThatReturnsAPromise)
.then(thirdFunctionThatReturnsAPromise)
.then(fourthFunctionThatReturnsAPromise);
return p;
};
现在外部函数只是另一个返回承诺的函数,意味着你 可以应用与内部函数相同的模式。
如果课程可以内联
var p = function() {
return new Promise(resolve, reject) {
DoSomethingAsync(function(err, result) {
if (err) {
reject();
} else {
resolve(result);
};
};
}).then(function() {
return new Promise(resolve, reject) {
DoSomethingAsync(function(err, result) {
if (err) {
reject(err);
} else {
resolve(result);
};
};
}).then(function() {
var err = DoSomethingNotAsync();
if (err) {
return Promise.reject(err);
} else {
return Promise.resolve();
}
});
等...
答案 1 :(得分:3)
就个人而言,当事情变得混乱依赖时,我更喜欢以下方法:
var externalAccount = Promise.join(payment, t, createExternalAccount),
externalTransaction = Promise.join(externalAccount, payment, t, createExternalTransaction),
address = Promise.join(externalAccount, payment, t, createAddress),
transaction = Promise.join(address, payment, createTransaction),
gatewayTransaction = Promise.join(externalTransaction, transaction, payment, t, createGatewayTransaction);
使一切变得更加清洁,尽管这是一种风格问题。
如果你想在获得gatewayTransaction
的价值后做某事(当然是异步的),你可以这样做:
gatewayTransaction
.then(function (val) {
// do stuff
})
.catch(function (err) {
// do stuff
});
你应该知道这里有一个微妙的陷阱。定义promise的顺序不一定是调用函数的顺序。这就是依赖关系的样子:
externalAccount -----> externalTransaction -----> gatewayTransaction
|--> address --> transaction --|
虽然这对性能有好处,但您可能希望将整个事情顺序化(就像您的回调金字塔一样)。在这种情况下,您可以写:
var externalAccount = Promise.join(payment, t, createExternalAccount),
externalTransaction = Promise.join(externalAccount, payment, t, createExternalTransaction),
address = Promise.join(externalAccount, payment, t, externalTransaction, createAddress),
transaction = Promise.join(address, payment, createTransaction),
gatewayTransaction = Promise.join(externalTransaction, transaction, payment, t, createGatewayTransaction);
通过将externalTransaction
添加到address
的依赖项(即使不需要它的值),您可以强制它是顺序的。