Cómo encadenar y compartir resultados anteriores con Promesas [duplicado]

Resuelto user1513388 asked hace 9 años • 1 respuestas

Estoy usando la biblioteca bluebird y necesito realizar una serie de solicitudes HTTP y necesito algunos de los datos de respuesta para la siguiente solicitud HTTP. Creé una función que maneja mis solicitudes llamada callhttp(). Esto requiere una URL y el cuerpo de un POST.

Lo llamo así:

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 primera solicitud obtiene una clave API que debe pasarse a la segunda solicitud y así sucesivamente. ¿Cómo obtengo los datos de respuesta de la primera solicitud?

ACTUALIZAR

Esta es la callhttpfunción:

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 );
        }
    });
}
user1513388 avatar Feb 25 '15 15:02 user1513388
Aceptado

Edite en 2023. Ahora que tenemos async/awaiten todos los entornos Javascript que ejecuta en estos días, la verdadera respuesta a esto es usar, async/awaitya que simplifica enormemente la recopilación y el uso de resultados intermedios en variables Javscript normales que se pueden usar en cualquier parte del secuencia. Vea el final de esta respuesta para esa conclusión. Las otras partes de esta respuesta se escribieron en 2015 antes de que async/await estuviera ampliamente disponible.

Existen algunos modelos para promesas dependientes y para pasar datos de una a otra. Cuál funciona mejor depende de si solo necesita los datos anteriores en la próxima llamada o si necesita acceso a todos los datos anteriores. Aquí tienes varios modelos:

Alimentar el resultado de uno al siguiente

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

Asignar resultados intermedios a un alcance superior

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

Acumular resultados en un objeto

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, para poder acceder a todos los resultados anteriores

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

Rompe la cadena en piezas independientes y recoge los resultados.

Si algunas partes de la cadena pueden proceder de forma independiente, en lugar de una tras otra, entonces puede iniciarlas por separado y usarlas Promise.all()para saber cuándo están terminadas esas múltiples piezas y luego tendrá todos los datos de esas piezas independientes:

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

Secuencia con awaiten ES7

Dado que la cadena de promesa es solo un mecanismo para secuenciar operaciones asincrónicas, en ES7 también puede usar awaity luego todos los resultados intermedios están disponibles en el mismo alcance (quizás más simple que los alcances separados de los .then()controladores encadenados):

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
});
jfriend00 avatar Feb 25 '2015 08:02 jfriend00