node.js - NodeJS,如何强制异步 for 循环在传递到下一次迭代之前等待 HTTP 请求解析,这样我们就不会收到 EMFILE 错误?

标签 node.js http for-loop asynchronous foreach

我正在尝试集成到自定义 API 中,我从数据库中获取一些行,然后为每一行连接到 API。 事情是,当数据库返回 3000 行或更少时,API 返回正确的响应,当我 POST 超过 3000 行时,我得到以下结果:

EMFILE ERROR -> OS won't allow the opening of more sockets

我相信 API 不会允许超过 3000 个 HTTP 请求 我尝试了 Promise/async-await 方法来等待 HTTP 请求结束,但没有成功,唯一一次当我添加 sleep 函数等待 200 毫秒或更长时间时它才起作用

这是我原来的函数:

    async function send_data(rows){
    let a=0;    
    log.info("Emails to integrate: "+rows.length);
    if(rows.length){
      for(const row of rows){
        log.info(row.email+" --- "+row.name+" --- "+row.id);
        await integrate_data(row,a);
        //await sleep(50);
        a++;
      }
      log.info("Finished integration, setting last ID");
    } else {
      log.info("No data to integrate");
    }
}

function integrate_data(row,counter){
        var options = {
          "method": "POST",
          "hostname": "API-URL",
          "path":"PATH/EMAIL/"+row.email,
          "headers": {
            "Content-Type": "application/json"
          }
        };
        var req = http.request(options, function (res) {
          var chunks = [];

          res.on("data", function (chunk) {
            chunks.push(chunk);
          });

          res.on("end", function () {
            var body = Buffer.concat(chunks);
            log.info(body.toString());
          });
        });

        let obj;
          obj = { 
            key1: row.name,
            key2: row.id, 
            key3: row.iterationNumber
         }

        req.write(JSON.stringify(obj));
        req.end();
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

是否有办法等待 HTTP 事务完成,然后进入下一次迭代,以便该函数可以打开连接、推送数据、关闭连接,然后发出信号以进入下一次迭代?

提前致谢

最佳答案

awaitintegrate_data(...) 没有按照您的想法进行。您不会等到请求完成,您的代码就会执行

req.write(JSON.stringify(obj)); 
req.end();

然后进入下一个迭代。

为了使 await 按预期工作,integrate_data 必须返回一个 Promise,并应在请求完成时解析。

function integrate_data(row, counter) {
    var options = {
        "method": "POST",
        "hostname": "API-URL",
        "path": "PATH/EMAIL/" + row.email,
        "headers": {
            "Content-Type": "application/json"
        }
    };

    return new Promise((resolve, reject) => {

      var req = http.request(options, function(res) {
          var chunks = [];

          res.on('error', reject);

          res.on("data", function(chunk) {
              chunks.push(chunk);
          });

          res.on("end", function() {
              var body = Buffer.concat(chunks);
              log.info(body.toString());
              resolve(body.toString()); // resolve promise
          });
      });

      let obj;
      obj = {
          key1: row.name,
          key2: row.id,
          key3: row.iterationNumber
      }

      req.write(JSON.stringify(obj));
      req.end();
    });
}

关于node.js - NodeJS,如何强制异步 for 循环在传递到下一次迭代之前等待 HTTP 请求解析,这样我们就不会收到 EMFILE 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51122605/

相关文章:

java - 当 Http Code!=200 时,Camel Rest 响应主体为空

由于循环,Swift 完成处理程序 For 循环将执行一次而不是 10 次

c# - 如果你正在破坏它的内容,那么迭代列表的最佳方法是什么

javascript - 如何将唯一 id 分配给与其行号对应的复选框(更新 : or item ID) under Bootstrap 4?

python-3.x - Python - 请求模块 - 检索网页时出现 HTTP 500 错误

windows - Golang : HTTP deployment under Windows

node.js - 如何使用 vanilla Node 发送由 Fiddler 接收的 HTTP 请求?

node.js - fs.writeFile() 不返回回调

node.js - 如何在一定时间内阻止api重复请求

node.js - 警告 : Task "karma" not found when running grunt test