代码之家  ›  专栏  ›  技术社区  ›  hamster121

如何在node.js中等待异步请求的for循环完成?

  •  2
  • hamster121  · 技术社区  · 6 年前

    res.setHeader('Content-Type', 'application/json');
    const sub = req.query.days_subtract;
    const enddate = req.query.end_date; 
    
    var array = [];
    
    for (var i = 0; i < sub; i++) {
      request("https://api.nasa.gov/planetary/apod?date=" + subtractDate(enddate, i) + "&api_key=DEMO_KEY", function(error, response, body) {
        array.push(body); 
        // console.log(body);
      });
    }
    res.send(array);
    

    但这段代码一直返回[]。我知道这是因为for循环只启动这些异步请求,而不是等待它们完成。我尝试使用async/await,但也没有成功。那么,如何等待这个循环完成获取请求并完成将它们推送到数组中,以便向用户显示它呢?

    4 回复  |  直到 6 年前
        1
  •  16
  •   Chris Diggs    4 年前

    对于您的用例,使用 await Promise.all 可能是最有效的方法。您的代码应该如下所示:

    res.setHeader('Content-Type', 'application/json');
    const sub = req.query.days_subtract;
    const enddate = req.query.end_date;
    
    var promiseArray = [];
    
    for (var i = 0; i < sub; i++) {
        promiseArray.push(new Promise((resolve, reject) => {
            request("https://api.nasa.gov/planetary/apod?date=" + subtractDate(enddate, i) + "&api_key=DEMO_KEY", function(error, response, body) {
            if (error) reject(error);
            else resolve(body)
        })
      }))
    }
    res.send(await Promise.all(promiseArray));
    
        2
  •  6
  •   Kon    5 年前

    request-promise . 如果您在for循环中等待每个请求,那么所有请求都是按顺序完成的。如果每个请求都是独立的,不需要一个接一个地执行,那么这是低效的。处理这样的事情的最好方法是并行地完成它们,然后等待它们全部完成。这是通过创建一个请求承诺数组,然后使用 await Promise.all(promiseArray) 等待所有承诺的实现。

    var promises = [];
    
    for (var i = 0; i < sub; i++) {
      const promise = request("https://api.nasa.gov/planetary/apod?date=" + subtractDate(enddate, i) + "&api_key=DEMO_KEY");
      promises.push(promise);
    }
    
    const array = await Promise.all(promises);
    
        3
  •  2
  •   Evert    6 年前

    要使用async/await,您需要使用返回承诺的HTTP库,而不是使用回调。

    node-fetch ,它有效地实现了浏览器实现的“fetchapi”。

    你可以简单地 await fetch(url) .

    async/await工作得非常好,而且正在变得非常普遍,我强烈建议您切换到将其视为一等公民而不是事后诸葛亮的框架和库。这包括Express,它也是一个基于回调的库,而不是基于承诺的库。但这有点离题。

        4
  •  2
  •   Aymeric Bouzy aybbyk    6 年前

    Promise async / await 语法非常清晰。

    但是,您似乎更喜欢使用回调。在这种情况下,您可以这样编写代码:

    res.setHeader('Content-Type', 'application/json');
    const sub = req.query.days_subtract;
    const enddate = req.query.end_date; 
    
    var array = [];
    var resultsCount = 0;
    
    for (var i = 0; i < sub; i++) {
      request("https://api.nasa.gov/planetary/apod?date=" + subtractDate(enddate, i) + "&api_key=DEMO_KEY", function(error, response, body) {
        if (error) { res.status(500) }
        array[i] = body
        // console.log(body);
        resultCount++;
        if (resultCount === sub) {
          res.send(array);
        }
      });
    }
    

    res.send 方法只在所有请求都返回其结果之后。