winegums008 winegums008 - 1 month ago 8
Node.js Question

Nodejs, Express and Mongo: callback function within the loop is being ignored

I've very new to NodeJS, Mongo and Express, so I apologise for what might seem like a simple question.

Incoming data that I'm trying to compare to has the following structure:

key1: {value1}
key2: {value2}
key3: {value3}


What I'm trying to do is, as data comes in, loop through the array, select each key, search the "assets" collection in mongo for a document that matches that key, If there is a match, compare {value1} of the incoming data against the {valueStored} of the match found within mongo.

Here is my code: `

app.all('/css', function(req, res, next) {
if (req.url === "/favicon.ico"){
res.sendStatus(200);
res.end();
}

var time = Math.floor(new Date() / 1000);
var cssFiles = req["body"]["css_information"]["css"];
var collection = database.collection("assets");
for (key in cssFiles){
if (cssFiles.hasOwnProperty(key)){
console.log("key outside find(): "+key);
// key above is cycling through properly, but key inside find() is stuck on last one
// so it isn't cycling through properly, and only searches for the last one everytime.
database.collection("assets").find({"path":key}).sort({"timestamp_changed" : -1}).limit(1).toArray(function (err, docs){
console.log("--docs inside find(): "+JSON.stringify(docs[0], null,4));
console.log("key inside find(): "+key);
if (docs[0] != null){
// console.log(JSON.stringify(docs[0]["css"], null, 4));
var lastCSS = docs[0]["css"];
if(lastCSS !== cssFiles[key]){
database.collection("assets", function(err, col3) {
collection.updateOne({"parent":"css", "timestamp_changed":time, "path":key,"css":cssFiles[key]},
{$set:{"path":key} },
{upsert: true, multi: false});
// database.close();
});
}else{
console.log("no changes");
//end of if lastCSS === cssFiles[key] statement
}
}else{
console.log("Key: "+key);
database.collection("assets", function(err, col3) {
collection.updateOne({"parent":"css", "timestamp_changed":time, "path":key,"css":cssFiles[key]},
{$set:{"path":key} },
{upsert: true, multi: false});
});
//end of if (doc[0] != null) statement
}
//end of find() callback
});
}else{
console.log("cssFiles ¬hasOwnProperty(key)");
}
//end of for loop
}
res.status(200).json({data:"RETURN STATUS"}).end();
});


`

When I run the code, it prints the following:

key outside find(): themes/seven/reset.css
key outside find(): themes/seven/style.css
key outside find(): sites/all/modules/ctools/css/ctools.css
key outside find(): modules/dblog/dblog.css
key outside find(): modules/overlay/overlay-child.css
key outside find(): sites/all/modules/panels/css/panels.css
key outside find(): modules/system/system.base.css
key outside find(): modules/system/system.admin.css
key outside find(): modules/system/system.menus.css
key outside find(): modules/system/system.messages.css
key outside find(): modules/system/system.theme.css
key outside find(): sites/all/modules/date/date_api/date.css
key outside find(): modules/field/theme/field.css
key outside find(): modules/node/node.css
key outside find(): modules/search/search.css
key outside find(): modules/user/user.css
key outside find(): sites/all/modules/views/css/views.css
executed
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css
key inside find(): sites/all/modules/views/css/views.css


How do I get the find() code to use the correct key and not get stuck on the last one every time? Or have I approached this completely incorrectly?

Answer

Since JavaScript is asynchronous, each query is executed after the loop is finished, so with the last key (which changes at each loop execution).

Yo have to copy your key and run the query with the copy:

let localKey = key;
database.collection("assets").find({"path":localKey}).sort( <etc with localKey instead of key>