Каков наилучший способ передачи разрешенных значений обещаний до конечной "затем" цепочки
Я пытаюсь обойти promises, используя Q-модуль в node.js, однако у меня небольшая проблема.
В этом примере:
ModelA.create(/* params */)
.then(function(modelA){
return ModelB.create(/* params */);
})
.then(function(modelB){
return ModelC.create(/* params */);
})
.then(function(modelC){
// need to do stuff with modelA, modelB and modelC
})
.fail(/*do failure stuff*/);
Метод .create возвращает обещание в каждом .then(), как и ожидалось, получает разрешенное значение обещания.
Однако в последнем .then() мне нужно иметь все 3 ранее разрешенных значения обещания.
Каким будет лучший способ сделать это?
Ответы
Ответ 1
Вот некоторые из ваших многочисленных опций:
За дверью 1 используйте сокращение, чтобы скопировать результаты последовательно.
var models = [];
[
function () {
return ModelA.create(/*...*/);
},
function () {
return ModelB.create(/*...*/);
},
function () {
return ModelC.create(/*...*/);
}
].reduce(function (ready, makeModel) {
return ready.then(function () {
return makeModel().then(function (model) {
models.push(model);
});
});
}, Q())
.catch(function (error) {
// handle errors
});
За дверью 2 упакуйте накопленные модели в массив и распакуйте с расширением.
Q.try(function () {
return ModelA.create(/* params */)
})
.then(function(modelA){
return [modelA, ModelB.create(/* params */)];
})
.spread(function(modelA, modelB){
return [modelA, modelB, ModelC.create(/* params */)];
})
.spread(function(modelA, modelB, modelC){
// need to do stuff with modelA, modelB and modelC
})
.catch(/*do failure stuff*/);
За дверью 3 запишите результаты в родительскую область:
var models [];
ModelA.create(/* params */)
.then(function(modelA){
models.push(modelA);
return ModelB.create(/* params */);
})
.then(function(modelB){
models.push(modelB);
return ModelC.create(/* params */);
})
.then(function(modelC){
models.push(modelC);
// need to do stuff with models
})
.catch(function (error) {
// handle error
});
Ответ 2
Библиотека Bluebird promises предоставляет другое решение для этого через .bind()
.
Он выглядит следующим образом:
ModelA.create(/* params */).bind({})
.then(function (modelA) {
this.modelA = modelA;
return ModelB.create(/* params */);
})
.then(function (modelB) {
this.modelB = modelB;
return ModelC.create(/* params */);
})
.then(function (modelC) {
// you have access to this.modelA, this.modelB and modelC;
});
В документации имеется много интересной информации об этом методе.
Ответ 3
Вероятно, вам не нужно ждать, пока будет создан modelA для создания модели и т.д.
Если это так, вы можете сделать следующее:
var promises = [
ModelA.create(...),
ModelB.create(...),
ModelC.create(...)
);
Q.all( promises ).spread(function( modelA, modelB, modelC ) {
// Do things with them!
}).fail(function() {
// Oh noes :(
});
Что это такое:
- Создайте массив promises с одним обещанием для каждой модели, которая вам нужна;
- Параллельно выполнить все 3 promises;
- Выполните функцию, переданную в
spread()
, когда все 3 promises выполнены. Аргументы - это разрешенные значения для каждого обещания в порядке объявления.
Надеюсь, это вам поможет:)