(я понимаю, что этот вопрос немного стар, но если вам все еще нужна помощь)
Это потому, что вы подталкиваете к array
, который находится за пределами callback
и async
природыJavaScript
вбрасывание.
Вот простое объяснение, почему оно пустое
var catsObjectId = new Array();
var data = new Array();
Recipe.find((err,doc3)=> {
// say execution 1
for (var i = 0; i < data.length; i++) {
catsObjectId.push([]);
data[i]['categories'].forEach((item, index) => {
// say execution 2
Recipecat.findOne({_id: item}, (err,result)=> {
item = result.name;
catsObjectId.push(item);
});
})
}
// say execution 3
console.log(catsObjectId);
});
Сначала выполняется execution 1
.В этом forEach
перебирает каждый элемент и запускает execution 2
.Затем продолжает выполнение execution 3
.
Проблема в том, что execution 2
является асинхронным, и значение возвращается когда-то в future
.Это будущее после excution 3
.Когда Recipecat.findOne
заканчивает выполнение, вызывается callback
в пределах then(result..
.Но console.log(catsObjectId)
уже выполнен и catsObjectId
был пуст во время выполнения.
Вы должны либо использовать catsObjectId
в обратном вызове .then((data) => // use data here)
, либо использовать async/await
, чтобы сделать его sync
как.
Примечание await
действует только внутри async
функция
async function getSomeNames() {
try {
const data = await Recipe.find();
// docs is an array of promises
const docs = data.map((item, index) => {
Recipecat.findOne({_id: item})
});
// items is an array of documents returned by findOne
const items = await Promise.all(docs);
// now you can map and get the names
const names = items.map(item => item.name);
} catch (e) {
// handle error
console.error(e);
}
}
getSomeNames()