node.js:如何在forEach循环中实现一个带有异步调用的路由方法

node.js: how to implement a routing method with an async call inside a forEach loop?

本文关键字:一个 异步 方法 路由 调用 js forEach 实现 循环 node      更新时间:2023-09-26

我必须实现这样的逻辑:

var express = require('express'),
    request = require('request');
var array = [
  { url: 'http://www.example1.com' },
  { url: 'http://www.example2.com' },
];
express.Router().get('/job', function (req, res) {
  results = [];
  array.forEach(function (item) {
    request(item.url, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        results.push(body);
      }
  });
  res.json(results); // <== wrong, results array is empty, here...
});

我如何调用res.json(结果)确保forEach循环结束?

UPDATE:它是不是建议答案的副本!

当所有请求完成时,我需要res.json(),当forEach循环完成时,不是…: - (

有一个简单的方法:

var express = require('express'),
    request = require('request');
var array = [
  { url: 'http://www.example1.com' },
  { url: 'http://www.example2.com' },
];
//store number of completed calls
var completed = 0;
express.Router().get('/job', function (req, res) {
  results = [];
  array.forEach(function (item) {
    request(item.url, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        results.push(body);
        completed = completed + 1; //iterate counter
        onComplete(); //attempt completion
      }
  });
  function onComplete(){
    if(completed != array.length) {
      return;
    }
    res.json(results); 
    // ... rest of code that relies on results
  };
});

您可以使用asnyc series来实现这一点。像这样:

var express = require('express'),
    request = require('request');
    async = require('async);

async.series([
    function(callback) {
        request('http://www.example1.com', function (error, response, body) {
            if (!error && response.statusCode == 200) {
                callback(null, body);
            }
        });
    },
    function(callback) {
        request('http://www.example2.com', function (error, response, body) {
            if (!error && response.statusCode == 200) {
                callback(null, body);
            }
        });
    }
], function(err, res) {
    res.json(res);
});

你应该使用承诺!(这个例子适用于最新版本的node,因为它支持原生承诺)

var arrayPromises = [];
array.forEach(function (item) {
   arrayPromises.push(new Promise(function(resolve, reject) {
       request(item.url, function (error, response, body) {
          if (!error && response.statusCode == 200) {
             resolve(body);
          }else{
            resolve();
          }
       });
   }));
});
Promise.all(arrayPromises).then(function(results){
  res.json(results);
});