Ответ 1
Я точно знаю, что вы просите, но.
Ниже приведена следующая цепочка обещаний, и она кажется довольно беспорядочной (каждая функция _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);
});
});
Я знаю, что существуют функции Promise, которые я могу использовать, например, all()
и join()
, но они, похоже, запускают функции, которые я не могу выполнять, потому что для сохранения некоторых таблиц требуются поля из ранее сохраненных таблиц. Я надеюсь, что для меня есть способ сделать что-то вроде следующего, но я не могу понять, как:
Promise.all(_this._createExternalAccount(payment, t), _this._createExternalTransaction(externalAccount, payment, t), _this._createAddress(externalAccount, payment, t))
.then(function(externalAccount, externalTransaction, address) {
// do logic
});
Я точно знаю, что вы просите, но.
Лично, когда ситуация становится беспорядочной с зависимостями, я предпочитаю следующий подход:
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
});
Здесь есть одна тонкая ловушка, о которой вы должны знать. Порядок, в котором определены promises, не обязательно является порядком, в котором вызываются функции. Вот как выглядят зависимости:
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
(хотя его значение не требуется), вы можете заставить его быть последовательным.