【问题标题】:How to write a non-blocking for loop in node js如何在节点 js 中编写非阻塞 for 循环
【发布时间】:2020-10-20 16:31:43
【问题描述】:

我在 mongoose db 中有两个集合。我必须找到集合中的所有文档。之后,我必须遍历所有文档以在第二个集合中找到相应的文档。为此,我正在考虑使用for 循环。但是,因为它本质上是blocking。我该如何执行我的任务。

const docs = await collection1.find({name:"asdf"})
for(let i=0;i<docs.length;i++){
    const doc2 = await collection2.findOne({address:docs.address})
}

【问题讨论】:

  • 根本没有阻塞!当数据库在循环内(await collection2.findOne(...))检索结果时,主线程正在处理“其他事情”。 Async/await 不会阻塞事件循环,简单来说await 只是对承诺和回调的嵌套进行糖衣,这样你的代码结构看起来“扁平”。在循环内(或代码中的任何位置)读取带有fs.readFileSync() 的文件之类的操作会阻塞事件循环,但await 并非如此。

标签: javascript node.js mongodb mongoose nonblocking


【解决方案1】:

我不确定我是否真的理解你的问题,但如果我理解了,我认为你可以将你所有的 Promise 推送到一个数组中,而不是使用 await。之后,您可以使用函数Promise.all 就地等待数组内的所有承诺。您可以在下面找到代码示例:

const docs = await collection1.find({name:"asdf"})
const docs2 = [];
for(let i=0;i<docs.length;i++){
    docs2.push(collection2.findOne({address:docs.address}));
}

Promise.all(docs2).then((values) => {
  // at this point all your documents are ready
  // and your for is not blocking
  console.log(values);
});

但是你必须小心不要滥用这个,如果你用很多承诺填充一个数组,它可能会导致性能/内存问题。 问候

【讨论】:

  • 对不起,但我想问的是我是否会使用 for 循环,然后它会阻塞事件循环。我如何避免使用 for 循环或使用它以使其不会阻塞事件循环
  • @anitashrivastava for 循环本身是“阻塞的”,但它很快。只是不要在循环中做任何阻塞(如this answer所示),你应该没问题。
  • 对不起,我是node js的新手,如何将找到的结果推送到相应的doc数组对象的索引?
  • 在我的示例中,值,就在“then”之后,它是一个数组。它包含您的所有文档
  • 现在,在使用此代码之前,请考虑这样一个事实,即您将使用并行查询(可能有数千个!)淹没您的数据库,并且此代码可能应该使用 collection2.find() 运行返回您需要的所有文档,而不是速度慢得多的单个 findOne() 调用。基本上在任何类型的循环中运行findOne(),无论是否有承诺,都是数据库客户端反模式和性能代码气味。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-11
  • 2016-09-18
  • 1970-01-01
  • 2011-12-21
  • 2011-08-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多