使用NodeJS异步调用多个API,而与每个结果无关

时间:2019-03-31 07:37:34

标签: node.js asynchronous concurrency

我正在尝试使用NodeJS调用多个端点,并且给出结果,但是问题是,在所有请求获得200或某个有效的HTTP响应后,它给出了结果。我想做的是获得所有结果,而与其他API无关。 例如,如果我呼叫3个端点,即。 A,B,C。如果端点B由于服务器问题而延迟了响应,则我的代码不应等待B完成请求并发送其他已完成请求的响应。

我正在使用Async Promise,但没有给出期望的输出。当最慢的API请求完成时,它将打印所有结果。

const request = require('request');

var requestAsync = function(url) {
    return new Promise((resolve, reject) => {
        var req = request(url, (err, response, body) => {
            if (err) return reject(err, response, body);
            resolve(JSON.parse(body));
        });
    });
};

const urls = [
    'https://jsonplaceholder.typicode.com/posts',
    'https://jsonplaceholder.typicode.com/albums',
    'https://jsonplaceholder.typicode.com/users',
    'http://localhost/local/node/1.php',
];


var getParallel = async function() {
    //transform requests into Promises, await all
    try {
        var data = await Promise.all(urls.map(requestAsync));
    } catch (err) {
        console.error(err);
    }
    console.log(data);
}

getParallel();

3 个答案:

答案 0 :(得分:0)

使用Promise.race以确保返回的Promise将在不超过指定的时间间隔后解决(或拒绝)。例如,以下内容将确保Promise.all在3000毫秒后会解决或拒绝:

var requestAsync = function(url) {
    return Promise.race([
        new Promise(resolve => setTimeout(resolve, 3000, 'too slow')),
        new Promise((resolve, reject) => {
            var req = request(url, (err, response, body) => {
                if (err) return reject(err, response, body);
                resolve(JSON.parse(body));
            });
        })
    ]);
};

如果您要拒绝是否花费了太长时间,只需将reject传递到setTimeout而不是resolve(其中reject是{ {1}}回调)。

答案 1 :(得分:0)

我不认为await(或Promise.all)对您要实现的目标没有帮助,除非(幸运的)您没有等待call()作为最后一次呼叫,否则将不得不等到await解决(或所有承诺都已解决或被拒绝)。

假设您有giveSome(),它可以执行一些异步工作并返回一个Promise。假设您有任务AB。 A在5s之后完成,B在1s之后完成。现在你要做

// called in parallel
// both a and b are promise pending
var a = giveSome() // task A
var b = giveSome() // task B

// do something with data in async function
console.log(await a) // this is resolved only after 5s
console.log(await b) // this is already resolved after 1s but waits for the await above

相反,如果您这样做:

a.then(val => console.log(val)) // outputs val after 5s
b.then(val => console.log(val)) // outputs val after 1s

因此,您可以:

var data = urls.map(requestAsync);

for (let i = 0; i < data.length; i++) {
  data[i]
    .then(val => console.log(val) // do something)
    // burden is you need to handle errors individually
    .catch(e => console.error(e))
}

答案 2 :(得分:0)

假设您要在每个响应之后调用方法FROM golang:1.12-alpine RUN mkdir /app WORKDIR /app ADD src/ /app ENV CGO_ENABLED=0 ENV GO111MODULE=off # Fetch application dependencies RUN apk add --no-cache --update git \ && go get github.com/bwmarrin/discordgo \ && go get github.com/jonas747/dshardmanager \ && go get github.com/bugsnag/bugsnag-go \ && apk del git # Build binary RUN go build -o main . CMD ["/app/main"] 。您可以创建另一个Promise来完成您的工作,而不必在请求调用时进行x。将每个请求包装在一个单独的Promise.all中,它将完成您的工作,然后使用另一个Promise来检查是否已全部执行。这是示例代码-

Promise.all