NodeJS,如何强制异步 for 循环在传递到下一次迭代之前等待 HTTP 请求解决,这样我们就不会收到 EMFILE 错误?
Posted
技术标签:
【中文标题】NodeJS,如何强制异步 for 循环在传递到下一次迭代之前等待 HTTP 请求解决,这样我们就不会收到 EMFILE 错误?【英文标题】:NodeJS, How to force the async for loop to wait the HTTP request to resolve before passing to the next iteration so we don't get the EMFILE error? 【发布时间】:2018-12-09 21:08:13 【问题描述】:我正在尝试集成到自定义 API 中,我从数据库中获取了一些行,然后对于连接到 API 的每一行。 问题是当数据库返回 3000 行或更少时,API 返回正确的响应,当我 POST 超过 3000 行时,我得到以下信息:
EMFILE ERROR -> OS won't allow the opening of more sockets
我相信 API 不允许超过 3000 个 HTTP 请求 我尝试了 promise/async-await 方法来等待 HTTP 请求以失败告终,这是我添加睡眠功能以等待 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 事务完成然后进入下一次迭代,以便该函数可以打开连接、推送数据、关闭连接然后发出信号以进行下一次迭代?
提前致谢
【问题讨论】:
【参考方案1】:await integrate_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();
);
【讨论】:
非常感谢@Marcos Casagrande,它的工作原理很有魅力 确实,我对 SO 以及 NodeJS 和 Async/Await/Promise 概念都是新手。我接受了答案,再次感谢你,伙计以上是关于NodeJS,如何强制异步 for 循环在传递到下一次迭代之前等待 HTTP 请求解决,这样我们就不会收到 EMFILE 错误?的主要内容,如果未能解决你的问题,请参考以下文章