Как написать неблокирующий цикл for в node js

#javascript #node.js #mongodb #mongoose #nonblocking

#javascript #node.js #mongodb #мангуст #неблокирующий

Вопрос:

У меня есть две коллекции в 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})
}
  

Комментарии:

1. Это вообще не блокировка! В то время как БД извлекает результаты внутри цикла ( await collection2.findOne(...) ), основной поток заботится о «других вещах». Async / await не блокирует цикл событий, простыми словами await , это просто приукрашивание вложенности обещаний и обратных вызовов, чтобы ваша структура кода выглядела «плоской». Что-то вроде чтения файла fs.readFileSync() внутри цикла (или где-либо в вашем коде) заблокирует цикл событий, но это не тот случай await .

Ответ №1:

Я не уверен, действительно ли я понимаю вашу проблему, но если я это сделаю, я думаю, вы можете поместить все свои обещания в массив вместо использования 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);
});
  

Но вы должны быть осторожны, чтобы не злоупотреблять этим, если вы заполняете массив множеством обещаний, это может привести к проблемам с производительностью / памятью.
С уважением

Комментарии:

1. извините, но я хотел спросить, буду ли я использовать цикл for, тогда он заблокирует цикл событий. Как я могу избежать использования цикла for или использовать его так, чтобы он не блокировал цикл событий

2. @anitashrivastava цикл for сам по себе «блокируется», но он быстрый. Просто не делайте ничего блокирующего В цикле (как показано в этом ответе), и все должно быть в порядке.

3. Извините, я новичок в node js, как я могу перенести найденный результат в индекс соответствующего объекта массива doc?

4. в моем примере значения, сразу после ‘then’ это массив. Он содержит все ваши документы

5. Теперь, прежде чем использовать этот код, подумайте о том, что вы будете заполнять свою базу данных параллельными запросами (их могут быть тысячи!) и что этот код, вероятно, должен выполняться с a collection2.find() , который возвращает все нужные вам документы вместо отдельных findOne() вызовов, которые намного медленнее. По сути, запуск findOne() внутри любого цикла, с обещаниями или без них, является антишаблоном клиента базы данных и запахом кода производительности.