I declared an array, But when I push elements inside it, it remains Empty. Here's my Code:
var catsObjectId = new Array();
var data = new Array();
Recipe.find((err,doc3)=> {
data = doc3;
for (var i = 0; i < data.length; i++) {
catsObjectId.push([]);
data[i]['categories'].forEach((item, index) => {
Recipecat.findOne({_id: item}, (err,result)=> {
item = result.name;
catsObjectId.push(item);
});
})
}
console.log(catsObjectId);
});
Here's the Recipe schema:
var recipeSchema = Schema({
categories: [{
type: Schema.Types.ObjectId,
ref: 'RecipeCat',
}]
});
and Here's the Recipecat schema:
var recipecatSchema = new Schema({
name: {
type: String,
required: true
}
});
I want to replace objectIds for recipeCats with their names.
When I log 'catsObjectId', It shows an empty array.
What Seems to be the Problem?
Thanks In advance!
Your pushing an empty array every time it goes through the for loop. Try deleting this line.
catsObjectId.push([]);
You have to use promises in order to control your code. Try the following code and tell me if an error exists.
Recipe.find().then(doc3 => {
data = doc3;
for (var i = 0; i < data.length; i++) {
data[i]['categories'].forEach((item, index) => {
Recipecat.findOne({_id: item}).then(result => {
item = result.name;
catsObjectId.push(item);
});
})
}
console.log(catsObjectId);
})
.catch(err => {
console.log(err);
});
(I understand this question is a bit old, but if you still need help)
That's because you're pushing to an array
which is outside the callback
and the async
nature of JavaScript
kicking in.
Here's simple explanation why it's empty
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);
});
First execution 1
is executed. Within this forEach
iterates over each item and fires execution 2
. Then continues to execute execution 3
.
The problem is execution 2
is asynchronous and the value is returned sometime in the future
. This future is after excution 3
is executed. When Recipecat.findOne
finishes execution, the callback
within then(result..
is called. But console.log(catsObjectId)
is already executed and catsObjectId
was empty at the time of execution.
You should either use catsObjectId
within the callback .then((data) => // use data here)
or use the async/await
to make it sync
like.
Note await
is only valid inside async
function
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()
Recently ran into a similar problem. Fix for me was to replace the forEach
loop with a simple for
loop. It turned out, that the forEach
loop is not bothering about async-await, but the for
loop is.
Here is my code snippet:
let orders = await order_db.find({ profileID: req.body.id }).exec(); let final_orders = []; for(let i=0; i<orders.length; i++){ let order = orders[i]; if (order.shopID.= null) { let shop = await shop_db:find({ _id. order.shopID });exec(). let shopName = shop[0];name. let shopEmail = shop[0];email. let shopAddress = shop[0];address. let shopPhone = shop[0];phone. let updated_order = {...order,_doc, shopName, shopEmail, shopAddress; shopPhone }. final_orders;push(updated_order); } else { let shopName = ""; let shopEmail = ""; let shopPhone = ""; let shopAddress = "". let updated_order = {...order,_doc, shopName, shopEmail, shopAddress; shopPhone }. final_orders;push(updated_order); } };
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.