如何使用 Promises 链接和共享先前的结果

2022-01-30 00:00:00 node.js javascript bluebird

我正在使用 bluebird 库,需要发出一系列 HTTP 请求,并且需要一些响应数据到下一个 HTTP 请求.我已经构建了一个函数来处理我的请求,称为 callhttp().这需要一个 url 和一个 POST 的正文.

I'm using the bluebird library and need to make a series of HTTP requests and need to some of the response data to the next HTTP request. I've built a function that handles my requests called callhttp(). This takes a url and the body of a POST.

我这样称呼它:

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

第一个请求获得一个 API 密钥,该密钥需要传递给第二个请求,依此类推.如何从第一个请求中获取响应数据?

The first request gets an API key which needs to be passed to the second request and so on. How do get the response data from the first request?

更新

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

推荐答案

有一些模型用于依赖 Promise 和从一个到下一个传递数据.哪一个效果最好取决于您是在下一次调用中只需要先前的数据还是需要访问所有先前的数据.这里有几个模型:

There are a few models for dependent promises and passing data from one to the next. Which one works best depends upon whether you only need the previous data in the next call or whether you need access to all prior data. Here are several models:

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

将中间结果分配给更高的范围

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

在一个对象中累积结果

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

嵌套,因此可以访问所有以前的结果

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

将链条分解成独立的部分,收集结果

如果链的某些部分可以独立进行,而不是一个接一个地进行,那么您可以单独启动它们并使用 Promise.all() 来了解这些多个部分何时完成并且您然后将拥有来自这些独立部分的所有数据:

Break the Chain into Independent Pieces, Collect Results

If some parts of the chain can proceed independently, rather than one after the other, then you can launch them separately and use Promise.all() to know when those multiple pieces are done and you then will have all the data from those independent pieces:

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

在 ES7 中使用 await 的序列

由于promise链只是一种对异步操作进行排序的机制,在ES7中,你也可以使用await,然后中间结果都在同一个作用域中可用(也许比单独作用域更简单)链接的 .then() 处理程序):

Sequence with await in ES7

Since the promise chain is just a mechanism for sequencing asynchronous operations, in ES7, you can also use await and then the intermediate results are all available in the same scope (perhaps simpler than the separate scopes of the chained .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
});

相关文章