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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28714298/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:17:47  来源:igfitidea点击:

How to chain and share prior results with Promises

javascriptnode.jsbluebird

提问by user1513388

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.

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

I'm calling it like this:

我这样称呼它:

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

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?

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

UPDATE

更新

This is the callhttpfunction:

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

回答by jfriend00

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:

有几个模型用于从一个到下一个依赖承诺和传递数据。哪个效果最好取决于您是否只需要在下一次调用中使用先前的数据,或者是否需要访问所有先前的数据。这里有几个模型:

Feed Result of One to the Next

一个到下一个的饲料结果

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

Assign Intermediate Results to Higher Scope

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

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

Accumulate Results in One Object

在一个对象中累积结果

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, so all Previous Results Can Be Accessed

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

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

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:

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

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

Sequence with awaitin ES7

awaitES7 中的序列

Since the promise chain is just a mechanism for sequencing asynchronous operations, in ES7, you can also use awaitand then the intermediate results are all available in the same scope (perhaps simpler than the separate scopes of the chained .then()handlers):

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

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