web-dev-qa-db-fra.com

Quelle est la meilleure façon de transmettre les valeurs de promesse résolues à une chaîne finale "puis"

J'essaie de tenir mes promesses en utilisant le module Q dans node.js, mais j'ai un petit problème.

Dans cet exemple:

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*/);

La méthode .create renvoie ensuite une promesse dans chaque .then (), comme prévu on obtient la valeur résolue de la promesse.

Cependant, dans le .then final (), je dois avoir les 3 valeurs de promesse précédemment résolues.

Quelle serait la meilleure façon de faire cela?

26
MoSs

Voici quelques-unes de vos nombreuses options:

Derrière la porte 1, utilisez réduire pour accumuler les résultats en série.

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
});

Derrière la porte 2, emballez les modèles accumulés dans un tableau et déballez-les avec de la pâte à tartiner.

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*/);

Derrière la porte 3, capturez les résultats dans la portée parent:

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
});
36
Kris Kowal

La bibliothèque de promesses Bluebird fournit une autre solution pour cela via .bind().

Cela ressemble à ceci:

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;
});

Il y a beaucoup d'informations intéressantes sur cette méthode dans le documentation .

23
justmoon

Vous n'avez probablement pas besoin d'attendre que modelA soit créé pour créer modelB et ainsi de suite.
Si cela est vrai, vous pouvez effectuer les opérations suivantes:

var promises = [
  ModelA.create(...),
  ModelB.create(...),
  ModelC.create(...)
);

Q.all( promises ).spread(function( modelA, modelB, modelC ) {
  // Do things with them!
}).fail(function() {
  // Oh noes :(
});

Ce que cela signifie:

  • Créez un tableau de promesses, avec une promesse pour chaque modèle dont vous avez besoin;
  • Exécutez les 3 promesses en parallèle;
  • Exécutez une fonction passée dans spread() lorsque les 3 promesses sont terminées. Les arguments sont les valeurs résolues pour chaque promesse, dans l'ordre de déclaration.

J'espère que ça t'aide :)

3
gustavohenke