web-dev-qa-db-fra.com

Comment enchaîner et partager les résultats antérieurs avec Promises

J'utilise la bibliothèque bluebird et j'ai besoin de faire une série de requêtes HTTP et j'ai besoin de certaines des données de réponse à la prochaine requête HTTP. J'ai construit une fonction qui gère mes requêtes appelée callhttp(). Cela prend une URL et le corps d'un POST.

Je l'appelle comme ça:

var payload = '{"Username": "joe", "Password": "password"}';
var join = Promise.join;
join(
    callhttp("172.16.28.200", payload),
    callhttp("172.16.28.200", payload),
    callhttp("172.16.28.200", payload),
    function (first, second, third) {
    console.log([first, second, third]);
});

La première demande obtient une clé API qui doit être transmise à la deuxième demande, etc. Comment obtenir les données de réponse de la première demande?

MISE À JOUR

Voici la fonction callhttp:

var Promise = require("bluebird");
var Request = Promise.promisify(require('request'));

function callhttp(Host, body) {

    var options = {
        url: 'https://' + Host + '/api/authorize',
        method: "POST",
        headers: {
            'content-type': 'application/json'
        },
        body: body,
        strictSSL: false
    };

    return Request(options).spread(function (response) {
        if (response.statusCode == 200) {
           // console.log(body)
            console.log(response.connection.getPeerCertificate().subject.CN)
            return {
                data: response.body
            };
        } else {
            // Just an example, 200 is not the only successful code
            throw new Error("HTTP Error: " + response.statusCode );
        }
    });
}
52
user1513388

Il existe quelques modèles de promesses dépendantes et de transmission de données de l'une à l'autre. Celui qui fonctionne le mieux dépend si vous n'avez besoin que des données précédentes lors du prochain appel ou si vous avez besoin d'accéder à toutes les données précédentes. Voici plusieurs modèles:

Résultat du flux de l'un à l'autre

callhttp(url1, data1).then(function(result1) {
     // result1 is available here
     return callhttp(url2, data2);
}).then(function(result2) {
     // only result2 is available here
     return callhttp(url3, data3);
}).then(function(result3) {
     // all three are done now, final result is in result3
});

Attribuer des résultats intermédiaires à une portée plus élevée

var r1, r2, r3;
callhttp(url1, data1).then(function(result1) {
     r1 = result1;
     return callhttp(url2, data2);
}).then(function(result2) {
     r2 = result2;
     // can access r1 or r2
     return callhttp(url3, data3);
}).then(function(result3) {
     r3 = result3;
     // can access r1 or r2 or r3
});

Accumuler les résultats dans un seul objet

var results = {};
callhttp(url1, data1).then(function(result1) {
     results.result1 = result1;
     return callhttp(url2, data2);
}).then(function(result2) {
     results.result2 = result2;
     // can access results.result1 or results.result2
     return callhttp(url3, data3);
}).then(function(result3) {
     results.result3 = result3;
     // can access results.result1 or results.result2 or results.result3
});

Nest, pour que tous les résultats précédents soient accessibles

callhttp(url1, data1).then(function(result1) {
     // result1 is available here
     return callhttp(url2, data2).then(function(result2) {
         // result1 and result2 available here
         return callhttp(url3, data3).then(function(result3) {
             // result1, result2 and result3 available here
         });
     });
})

Brisez la chaîne en morceaux indépendants, collectez les résultats

Si certaines parties de la chaîne peuvent procéder indépendamment, plutôt que l'une après l'autre, alors vous pouvez les lancer séparément et utiliser Promise.all() pour savoir quand ces multiples pièces sont terminées et vous aurez alors toutes les données de celles-ci pièces indépendantes:

var p1 = callhttp(url1, data1);
var p2 = callhttp(url2, data2).then(function(result2) {
    return someAsync(result2);
}).then(function(result2a) {
    return someOtherAsync(result2a);
});
var p3 = callhttp(url3, data3).then(function(result3) {
    return someAsync(result3);
});
Promise.all([p1, p2, p3]).then(function(results) {
    // multiple results available in results array
    // that can be processed further here with
    // other promises
});

Séquence avec await dans ES7

Étant donné que la chaîne de promesses n'est qu'un mécanisme de séquencement des opérations asynchrones, dans ES7, vous pouvez également utiliser await, puis les résultats intermédiaires sont tous disponibles dans la même étendue (peut-être plus simple que les étendues distinctes des chaînes chaînées .then() handlers):

async function someFunction(...) {

    const r1 = await callhttp(url1, data1);

    // can use r1 here to formulate second http call
    const r2 = await callhttp(url2, data2);

    // can use r1 and r2 here to formulate third http call
    const r3 = await callhttp(url3, data3);

    // do some computation that has access to r1, r2 and r3
    return someResult;
}

someFunction(...).then(result => {
    // process final result here
}).catch(err => {
    // handle error here
});
124
jfriend00