#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()
внутри любого цикла, с обещаниями или без них, является антишаблоном клиента базы данных и запахом кода производительности.