如何使用 Promises 链接和共享先前的结果 [重复]

Posted

技术标签:

【中文标题】如何使用 Promises 链接和共享先前的结果 [重复]【英文标题】:How to chain and share prior results with Promises [duplicate] 【发布时间】:2015-04-27 04:02:08 【问题描述】:

我正在使用 bluebird 库,需要发出一系列 HTTP 请求,并且需要一些响应数据到下一个 HTTP 请求。我构建了一个函数来处理我的请求,称为callhttp()。这需要一个 url 和一个 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 密钥,该密钥需要传递给第二个请求,依此类推。如何从第一个请求中获取响应数据?

更新

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

【问题讨论】:

是的,位工作正常,它返回一个承诺,所以连接工作正常。 我正在使用请求库并已承诺。 您在问题中显示的对callhttp() 的三个调用正在并行处理,因此您不能在其他调用中使用其中任何一个的结果。 callhttp() 也返回一个承诺吗? 你能添加你的callhttp函数吗? 刚刚添加了callhttp函数 【参考方案1】:

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

从一个到下一个的馈送结果

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() 知道这些多个部分何时完成,然后您将获得来自这些独立部分的所有数据件:

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,然后中间结果都在同一个作用域中可用(可能比链式@987654330的单独作用域更简单) @处理程序):

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

【讨论】:

非常感谢 - 我现在就试试这些! 后两种方案也有讨论here 工作得很好,谢谢。 完美的代码,带来乐趣和利润。 @TravisBear - callhttp 可以是任何异步操作,它返回一个在异步操作完成时被解析或拒绝的承诺。这个答案所基于的原始问题中有一个实现,但它可以是任何返回承诺的异步操作。

以上是关于如何使用 Promises 链接和共享先前的结果 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Angular 8 - 如何使用 Promises 和 Async/Await [重复]

关于链接es6 Promises,然后()和价值消费

流星:如何根据先前选择的结果进行选择

(mongoose/promises) 如何检查文档是不是是使用 findOneAndUpdate 和 upsert 创建的

Ios Facebook SDK 我如何共享图像、链接、文本?

核心数据:如何进行第二次获取仅限于先前获取的结果?