请求承诺循环,如何包含随响应发送的请求数据?

request-promise loop, how to include request data sent with response?

我正在尝试在循环中使用请求承诺,然后将包含所有响应的响应发送回客户端。下面的代码有效,但是我还想在每个响应中包含请求数据,以便请求 ID 可以与结果相关联。有没有内置的方法来做到这一点:

promiseLoop: function (req, res) {
    var ps = [];
    for (var i = 0; i < 3; i++) {
        // var read_match_details = {
        //     uri: 'https://postman-echo.com/get?foo1=bar1&foo2=bar2',
        //     json: true // Automatically parses the JSON string in the response 
        // };
        var session = this.sessionInit(req, res);
        if (this.isValidRequest(session)) {
            var assertion = session.assertions[i];
            const options = {
                method: 'POST',
                uri: mConfig.serviceURL,
                body: assertion,
                headers: {
                    'User-Agent': 'aggregator-service'
                },
                json: true
            }
            logger.trace(options);
            ps.push(httpClient(options));
        }

    }

    Promise.all(ps)
        .then((results) => {
            console.log(results); // Result of all resolve as an array
            res.status(200);
            res.send(results);
            res.end();
        }).catch(err => console.log(err));  // First rejected promise
}

假设 httpClient() 是您所指的 request-promise 并且 assertion 值是您要通过此结果传递的值,您可以更改此:

ps.push(httpClient(options));

对此:

ps.push(httpClient(options).then(result => {
    return {id: assertion, result};
}));

然后,您的承诺将解析为包含结果和 ID 的对象,您可以访问最终结果数组中的每个对象。


您的代码没有显示当前结果是什么。如果它已经是一个对象,您也可以根据需要将 id 属性 添加到该对象。这完全取决于您如何将最终结果放在一起。

ps.push(httpClient(options).then(result => {
    // add id into final result
    result.id = assertion;
    return result;
}));

无论如何,一般的想法是在将 promise 放入数组之前,您使用 .then() 处理程序稍微修改返回的结果,添加您想要添加的任何数据,然后返回新的修改结果因此它成为承诺链的解析值。


为确保您处理所有响应,即使有些响应有错误,您可以使用较新的 [Promise.allSettled()][1] 而不是 Promise.all(),然后查看哪些响应在处理过程中成功或失败结果。或者,您可以捕获任何错误,将它们转化为已解决的承诺,但给它们一个重要的值(通常 null),您可以在处理最终结果时看到它:

ps.push(httpClient(options).then(result => {
    // add id into final result
    result.id = assertion;
    return result;
}).catch(err => {
    console.log(err);
    // got an error, but don't want Promise.all() to stop
    // so turn the rejected promise into a resolved promise
    // that resolves to an object with an error in it
    // Processing code can look for an `.err` property.
    return {err: err};
}));

然后,稍后在您的处理代码中:

Promise.all(ps)
    .then((results) => {
        console.log(results); // Result of all resolve as an array

        // filter out error responses
        let successResults = results.filter(item => !item.err);
        res.send(successResults );
    }).catch(err => console.log(err));  // First rejected promise

Promise.allSettled 不会在出错时停止。它确保您处理所有响应,即使有些响应有误。

const request = require('request-promise');
const urls = ["http://", "http://"];
const promises = urls.map(url => request(url));
Promise.allSettled(promises)
.then((data) => {
    // data = [promise1,promise2]
})
 .catch((err) => {
   console.log(JSON.stringify(err, null, 4));
 });