Getting empty array because of the asynchronous nature of Nodejs - node.js

Just started working with Nodejs and facing this issue while pushing the array as a response in the below code. I know this is happening because of the asynchronous nature of Nodejs, tried to apply async as well but did not get the desired result. Could someone let me know the fix of this code:
array = [];
var company = companySchema.Company;
company.findOne({_id: companySchema.objectId(req.tempStore.companyId)}, function (err, comp) {
if (err) {
console.log(err);
}
else {
var i;
var length = comp.events.length;
var dataset = datasetSchema.dataset;
for (i = 0; i < length; i++) {
dataset.find({companyId:comp.events[i]}, function (err,data) {
if (err) {
console.log(err);
}
else {
array.push(data);
}
console.log("array-----"+array); // prints array here
});
}
}
console.log("array-----"+array); // array is empty hence causing empty response
res.response.data = array;
next();
});

You can use mongoDB $in clause for this task:
var company = companySchema.Company;
company.findOne({_id: companySchema.objectId(req.tempStore.companyId)}, function (err, comp) {
if (err) {
console.log(err);
} else {
var dataset = datasetSchema.dataset;
dataset.find({companyId : {$in : comp.events}}, function (err, docs) {
if (err) {
console.log(err);
} else {
console.log("array: " + docs); // prints array here
res.response.data = docs;
next();
}
});
}
});

Related

node.js async/sync with For Loop, Query, and Additional function

Hello I am having an issue with the following sequence, I need to run multiple queries which build on each other that are in a for loop then once the final result is obtained to implement the result. I am having an issue where my for loop is looping past the query, also I need to stop the code while the findX function is running.
I know this is an async problem but I don't see how I could chain promises, or use the async npm package with needing to loop queries that depend on the result of the previous query. Thanks in advance.
function findX(){
//executes another query
}
function solve(res, connection, info, requestArr, callback){
var parentID = null;
var obj = {};
for (var i = 0; i <= requestArr.length; i++) {
connection.query("SELECT WHERE ", [parentID, requestArr[i]], function(err, results) {
if(results[0]['x']){
var obj = findX(x)
break;
}else{
parentID = results[0]['parentID'];
}
});
}
//Do stuff with obj only after the final result has been set in the for loop
}
You can use Async TimesSeries.
// Pretend this is some complicated async factory
var createUser = function(id, callback) {
callback(null, {
id: 'user' + id
});
};
// generate 5 users
async.times(5, function(n, next) {
createUser(n, function(err, user) {
next(err, user);
});
}, function(err, users) {
// we should now have 5 users
});
So, in your example would be something like this:
var iterations = requestArr.length - 1,
parentID,
obj;
var getResults = function (i, callback) {
connection.query("SELECT WHERE ", [parentID, requestArr[i]], function (err, results) {
if (results[0]['x']) {
obj = findX(x);
callback('done');
}
else {
parentID = results[0]['parentID'];
callback();
}
});
};
async.timesSeries(iterations, function (n, next) {
getResults(n, function (err) {
next(err);
});
}, function (err) {
// use obj
});

nodeJS Mongoose updating multiple documents & returning the changed values

I'm essentially trying to find all Tasks with a given scaler_ID and then set them their respective scaler_ID to -1 and then return all of the new tasks in the HTTP response.
Here's my code:
api.post('/unassignTasks', function(req, res) {
Task.find({scaler_ID: req.body.scaler_ID}, function(err, tasks) {
for (var i = 0; i < tasks.length; ++i) {
tasks[i].scaler_Id = -1;
console.log(tasks[i]);
(function(arrayIndex) {
tasks[i].save(function(err, result) {
if (err) { console.log(err); }
});
})(i);
res.send(tasks);
return;
}
});
For some reason this won't work and the scaler_ID is not being set to -1 to the elements in the database. Any ideas what is causing this?
Proper way by using async.each
//npm install async --save //don't forget to install it first
var async = require('async');
api.post('/unassignTasks', function(req, res) {
var id = req.body.scaler_ID;
Task.find({scaler_ID: id }, function(err, tasks) {
async.each(tasks, function(task, each_cb) {
task.scaler_Id = -1;
task.save(each_cb);
}, function(err) {
if(err)
return res.status(400).send(err);
res.send(tasks);
});
});
}

how to run code sequentially in node js

Hi I have this code but when finish the result is not the espected because didn't run in the sequence that I wish
here is the code:
var user_data = {};
models.games.find({$or: [{w_id: req.user._id}, {b_id: req.user._id}, {owner: req.user._id}]}, function (err, games) {
var req_games = [];
if (!err) {
for (var i in games) {
req_games.push(games[i]);
models.users.findOne({_id: games[i].w_id}, function (err, user) {
req_games[i].w_id = user.user;
console.log(req_games[i].w_id) //< -- 3
});
console.log('a ' + req_games[i].w_id) //<-- 2
}
user_data.games = req_games; // <-- 1
}
});
at the end of the task req_games didnt have any update because it's running in the sequence that I put in the comments in the code
This may help you using Q(promises)
obj.find = function(model, condition) { //make your find to return promise
var deferred = q.defer();
model.find(condition, function(err, results) {
if (err) {
logger.log(err);
deferred.reject(err);
} else {
deferred.resolve(results);
}
});
return deferred.promise;
}
ArraysOfId.forEach(function (id) {
var tempProm = mongoUtilsMethodObj.find(schemaObj.Asset, id).then(function (assetObj) {
---- your code
return q.resolve();
});
promArr.push(tempProm);//push all promise to array
});
q.all(promArr).then(function () {
// this will be called when all promise in array will we resolved
})
Here is a version using the async library to map your game values.
var async = require('async');
var user_data = {};
models.games.find({$or: [{w_id: req.user._id}, {b_id: req.user._id}, {owner: req.user._id}]}, function (err, games) {
if(err) {
// or whatever your error response happens to be
return res.render('user.swig', {error: err});
}
async.map(games, function(game, nextGame) {
models.users.findOne({_id: game.w_id}, function (err, user) {
game.w_id = user.user;
nextGame(err, game);
});
}, function(err, req_games) {
user_data.games = req_games;
res.render('user.swig', {user: user_data});
});
});

Not able to access result returned from mongoDb outside query

I am working with node.js using express and mongoDb.
I am trying to retrieve data from database "local" and collection "borrower" and pushing it into an empty array collectionOne. It is rendering this array on the view page.
I want to use _id pushed in an array b_ids from this output to make a call to company_details collection under same router .
The issue I am facing here is I am not getting any value in array b_ids when trying to access it under call to company_details collection.
The code is as below:
var collectionOne = [];
var collectionTwo = [];
var b_ids = [];
router.get('/fetch',function(req, res, next){
MongoClient.connect('mongodb://localhost:27017/local', function(err, db){
var collection = db.collection('borrower');
db.collection("borrower", function(err, collection) {
collection.find().toArray(function(err, result) {
if (err) {
throw err;
} else {
//console.log(result[0].first_name);
for (i=0; i<result.length; i++) {
collectionOne[i] = result[i];
b_ids[i] = result[i]._id;
}
}
});
db.collection("company_details", function(err, collection){
console.log(b_ids);
collection.find({borrower_id : {$in :b_ids}}).toArray(function(err, result){
if (err) {
throw err;
} else {
for (i=0; i<result.length; i++) {
collectionTwo[i] = result[i];
}
}
});
});
res.render('index',{data : collectionOne , data1 : collectionTwo});
});
});
});
Please suggest me how can I access the b_ids array here. Thanks in advance :)
The callback from toArray is asynchronous, i.e. will happen after your console.log line executes, therefore you need to re-arrange as follows:
var collectionOne = [];
router.get('/fetch',function(req, res, next){
MongoClient.connect('mongodb://localhost:27017/local', function(err, db){
var collection = db.collection('borrower');
db.collection("borrower", function(err, collection) {
collection.find().toArray(function(err, result) {
if (err) {
throw err;
} else {
for (i=0; i<result.length; i++) {
collectionOne[i] = result[i];
b_ids[i] = result[i]._id;
}
db.collection("company_details", function(err, collection){
console.log(b_ids);
collection.find({borrower_id : {$in :b_ids}}).toArray(function(err, result){
if (err) {
throw err;
} else {
for (i=0; i<result.length; i++) {
collectionTwo[i] = result[i];
}
res.render('index',{data : collectionOne , data1 : collectionTwo});
}
});
});
}
});
});
});
This ensures that the callback completes before you try and log / render it.
It is simple create a function with a callback function inside it as an argument
function returnBids(collection, callback){
collection.find().toArray(function(err, result) {
if (err)
throw err;
else
callback(result)
})
}
and you can access your result outside by calling the function returnbids() .i.e
returnBids(collection,function(b_ids){
console.log(b_ids)
})

Node.JS/MongoDB: document join solutions

I have been trying to do a 3 document join with mongodb and am going around in circles (literally). I am attempting to do this leveraging async inside a loop to grab the additional documents and then build a custom json document that will be passed into my page. I am having limited success with this and am wonder if anyone has tried this or has some suggestions.
MongoClient.connect("mongodb://localhost:27017/preInc", function(err, db) {
if(err) { return console.dir(err); }
var collection = db.collection('resource_Tbl');
collection.find().toArray(function(err, items)
{
if(err) {
return console.dir(err); }
else {
test = items;
}
for (var i = 0; i < items.length; i++)
{
var temp = items[i]._id.toHexString();
var name = items[i].name;
console.dir(temp + "-|-" + name);
Async.waterfall([
function getGeoAddress(callback)
{
console.dir(temp + " " + name);
callback(null, 'unknown');
},
],
function (err, results)
{
if (err)
{
console.log(err);
}
else
{
}
});
}
res.render('heatmap', { data: test, headerX:'preInc.org' });
});
});
});
the main problem I am running into now is that the loop works perfectly but the async does not start until after the loop has finished and only processes the last record (x times)
thank you in advance.
AEgir...

Resources