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

标签 javascript node.js bluebird

我正在使用 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 key ,需要将其传递给第二个请求,依此类推。如何从第一个请求中获取响应数据?

更新

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

最佳答案

2023 年编辑。现在,我们在您执行的每个 Javascript 环境中都有 async/await,真正的答案是使用 async/await 因为它极大地简化了中间结果的收集和使用,并将其转换为可在序列的任何部分使用的普通 Javscript 变量。请参阅此答案的末尾以了解该结论。这个答案的其他部分都是在 2015 年 async/await 广泛使用之前写的。

有一些用于依赖 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 ,然后中间结果都在同一个作用域中可用(也许比单独的作用域更简单)链接的 .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
});

关于javascript - 如何使用 Promise 链接和共享先前的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34128715/

相关文章:

node.js - 如何读取 gzip 中的 json 文件?

node.js - 由于未定义的 PropTypes.node,React 应用程序崩溃

javascript - 无法得到我在 nodejs/mongoose/bluebird 中返回的 promise

node.js - Promise.all 遭到未处理的拒绝

javascript - 在页面向下滚动时创建固定位置的文本,然后停止在某个位置

javascript - 如何让 .getAttribute 和 .removeAttribute 匹配 [onclick* ='ga' ]

javascript - 符号原型(prototype)的字符串表示?

node.js - 如何 promise AWS JavaScript 开发工具包?

javascript - 获取 ASP 文本框的更改值

javascript - ExpressJS 上的异步函数