cursor.forEach is not a function Node.js - javascript

Here I am trying to use forEach method to iterate through each document of the cursor and pushing it into the result array but i am getting an error at
forEach
here is my code :
var fetch = function(callback) {
// mongoose.connect('mongodb://localhost/registration');
mongoose.connect('mongodb://localhost/questiondb');
var cursor = user.find();
cursor.forEach(function (doc,err) {
if(!err)
resultArray.push(doc);
else
{
callback(false);
}
},
function () {
callback(resultArray);
});
};
error is :
TypeError: cursor.forEach is not a function

Mongoose's Model.find returns a Query object, not a cursor. Furthermore, if you pass a callback to find, you'll get just the behavior you're trying to create with fetch, where an array of documents are provided to the callback.
var fetch = function(callback) {
// Don't connect here, connect once during startup
// mongoose.connect('mongodb://localhost/questiondb');
user.find((err, resultArray) => {
if (!err) {
callback(resultArray);
}
else {
callback(false);
}
});
};

you need to convert in array
User.find(function (err,userx){
if (err){
throw err;
}
else{
//add this code sentence
var user_arr =Object.keys(userx).map(
function(key){
return userx[key];
}
);
//now, use forEach sentence
user_arr.forEach(function(us){
console.log(us.name);
})
}
})

Because the cursor is not an array.forEach function must be used on an array.

Related

ExpressJS function can't return

I've been trying to develop an app working on Electron with an Express webserver. I also use mysql npm package for database stuff. But there's something wrong with the login function and I wasn't able to find the problem. I hope you could help.
server.js
function userLogin(data){
con.query(`SELECT * FROM players WHERE player_username = '${data.login_username}'`, (err, result, fields) => {
if (err) throw err;
var compare = bcrypt.compareSync(data.login_password, result[0].player_password);
if(compare == true) {
return "1";
}
else{
return "0";
};
});
};
app.route('/login').post((req,res) => {
res
.json(userLogin(req.body))
.end();
});
Everything is defined. No errors are shown but the function can't return, I don't understand why. If I add a console.log above return, it logs the result so the query is also OK, but the function doesn't return anything, literally anything.
Since userLogin is an asynchronous function, you can't just call it like a normal function and expect it to return a value. Instead, you should work on its results from inside the callback of con.query when they are available, like so:
app.route('/login').post((req, res) => {
con.query(`SELECT * FROM players WHERE player_username = '${data.login_username}'`, (err, result, fields) => {
var compare = bcrypt.compareSync(data.login_password, result[0].player_password);
res.json(compare ? "1" : "0").end();
});
});
You have to wait for the query to complete before sending the response. One way is to convert it into Promise and another is to use a callback
function userLogin(data, onComplete){
con.query(`SELECT * FROM players WHERE player_username = '${data.login_username}'`, (err, result, fields) => {
if (err) throw err;
var compare = bcrypt.compareSync(data.login_password, result[0].player_password);
if(compare == true) {
onComplete("1"); // do callback function
}
else{
onComplete("0");
};
});
};
app.route('/login').post((req,res) => {
userLogin(req.body, (val) => {res.json(val).end(); } ) // pass the function as callback
});

How to update an array data in database using NodeJs Async?

I am new to NodeJs and I'm finding the Non Blocking and Asynchronous nature of JS extremely difficult to understand and handle,
I have a piece of code which is supposed to Iterate an array
and for every iteration, I'm supposed to make a DB update.
Can someone provide the correct implementation of Async library functions and help fix my code?
Code example -
function updateFunction(conn, requestBody, callback) {
let arr = [];
async.each(requestBody.arr, function(item, callback) {
let sqlData = []
let columns = "";
if(item.columnData != null){
sqlData.push(item.columnData);
columns += "`columnName` = ?,";
}
if(columns != ''){
columns = columns.substring(0,columns.length-1);
let sqlQuery = 'UPDATE someTable SET '+columns
+' WHERE id = "' + item.id + '"';
conn.query(sqlQuery, sqlData, function (err, result) {
if (err) {
return callback(err, false);
}
})
}
else{
return callback(null, false);
}
columns = "";
sqlData = [];
},
function(err, results) {
//Code never reaches here, don't know why
if (err) {
return callback(err, false);
}
else{
return callback(null, true);
}
});
} // END
During your database query call, on a successful query your callback is not called, therefore causing your code to never reach the final callback.
You will want to add another return statement after your if (err) { return callback(err); } to let async know your database query is finished.
And another thing, according to the docs, the async each method's final callback does not invoke with results in its callback.
A callback which is called when all iteratee functions have finished, or an error occurs. Invoked with (err).
Therefore, it is not required for you to pass a value into the callback statement within your iteratee function.
Modify your code to do this and it will work.
conn.query(sqlQuery, sqlData, function (err, result) {
if (err) {
return callback(err);
}
return callback(null);
})
Hope this helps.
conn.query(sqlQuery, sqlData, async function (err, result) {
if (err) {
return await callback(err, false);
}
})
Something like this.. so the function callback is async here and we gave await which actually waits until the return call is finished..

Series control flow with bluebird promises

I have a number of promises and I want to execute them in order, but conditionally.
For example, I have the following promises:
getItems()
getItemsSource()
getItemsAlternativeSource()
What I want to do is try getItems() first. If this resolves with an empty value OR if it throws an error, I want to log that error (if that's the case), but then try getItemsSource(), same as above, if it resolves with no value or throws an error, I want to log the error if that's the case and try getItemsAlternativeSource().
I know I can do this conditionally, in each then() or catch(), but that seems a bit redundant. Is there a better way to handle this kind of control flow?
Thank!
You can use an empty value as the return value of the catch handler:
getItems().catch(function(err) {
console.warn(err);
return null; // <==
}).then(function(items) {
if (items) return items;
else return getItemsSource().catch(function(err) {
console.warn(err);
return null; // <==
}).then(function(sourceitems) {
if (items) return items;
else return getItemsAlternativeSource().catch(function(err) {
console.warn(err);
throw new Error("items couldn't be fetched normally, from source, or from alternative source");
});
});
});
If you absolutely want to avoid duplication, you can use this highly abstract approach:
var tryAll = [getItems, getItemsSource, getItemsAlternativeSource].reduceRight(function(nextAlternative, fetch) {
return function() {
return fetch().then(function(items) {
if (items) return items;
else return nextAlternative(); // now we can even call it in two locations
}, function(err) {
console.warn(err);
return nextAlternative(); // without having to resort to catch-then
});
};
}, function last() {
throw new Error("items couldn't be fetched normally, from source, or from alternative source");
});
tryAll();
I'd suggest you create a function that takes an array of functions that will call each function in the array until one returns with some data.
function getFirstData(array) {
var index = 0;
function next() {
if (index < array.length) {
return array[index++]().then(function(data) {
// if we got an answer, return it as the resolve value
if (data) return data;
// otherwise, reject so we go to the next one
return Promise.reject(null);
}).catch(function(err) {
if (err) console.err(err);
return next();
});
} else {
// got to the end of the array without a value
throw new Error("No data found");
}
}
return Promise.resolve().then(next);
}
var fns = [getItem, getItemsSource, getItemsAlternativeSource];
getFirstData(fns).then(function(data) {
// got data here
}).catch(function(err) {
// no data found here
});
If you want the functions to have arguments, then you can .bind() the arguments to the functions before putting them in the array.
And, here's a different implementation using .reduce() to traverse the array:
function getFirstData(array) {
return array.reduce(function(p, fn) {
return p.then(function(priorData) {
// if we already got some data, then just return it
// don't execute any more functions
if (priorData) return priorData;
return fn().catch(function(err) {
console.log(err);
return null;
});
});
}, Promise.resolve()).then(function(data) {
if (!data) {
throw new Error("No data found");
}
});
}

a way to know when all callbacks are done in javascript

I have many calls to a service at the end of which i want to write to a file my final collection when all the callbacks of the service have returned.
is there there a way to be sure that all callbacks are done ?
for (id in idsCollection) {
object.callService(id, function (res) {
collection.push(res);
});
}
filewriter.writetoFile("filename.json", JSon.Stringify(collection));
EDIT : just for the record i'm using cheerio with nodeJS.
Create an array. Push something onto the array each time you set up a callback. Pop something off it each time the callback runs. Check to see if the array is empty inside the callback function. If it is empty, then all the callbacks are done.
I typically use the node-async library for this sort of thing. It makes it easy to do exactly what you're talking about:
async.each(yourArray,
function(element, next) {
// this callback gets called for each element in your array
element.doSomething(function(returnValue){
next(returnValue) // call next when you're done
}
}, function(err, returnValues) {
// when all the elements in the array are processed, this is called
if (err) return console.log(err);
console.log(returnValues) // this is an array of the returnValues
});
})
You could simply count them. In your case it seems you already know how many callbacks there are going to be.
var remaining = idsCollection.length; // assuming array
for (id in idsCollection) {
object.callService(id, function (res) {
collection.push(res);
remaining -= 1; // decrement by 1 per callback
// here you can check if remaining === 0 (all done)
});
}
you can use nimble lib http://caolan.github.io/nimble/.
nimble paralel example
var _ = require('nimble');
_.parallel([
function (callback) {
setTimeout(function () {
console.log('one');
callback();
}, 25);
},
function (callback) {
setTimeout(function () {
console.log('two');
callback();
}, 0);
}
], function(){
console.log('done')
});
output
> two
> one
> done
I see many answers here, but I hope that this solution may still help someone.
Create a promise for each callback to be extinguished as such:
function funcToLoop(arg){
return new Promise((resolve, reject) => {
try{
funcWithCallback(arg, (cbArg) => {
// do your stuff
resolve(cbArg)
});
} catch (e) {
reject(e)
}
});
}
Then, you can create a loop as a async function and handle eventual results/states/etc here:
async function mainLoop(array){
let results = [];
for (let arg of array){
results.push(await funcToLoop(arg))
}
// handle results
}
... or you can have a sync function, collect the promises and handle them:
function mainLoop(array){
let promises = [];
for (let arg of array){
promises.push(funcToLoop(arg))
}
Promise.all(promises).then(()=>{
// handle promises
})
}
Claudio
jQuery.Deferred() objects might be what you are looking for.
OR if you are using HTML5 you can use promises .
Here is how to create promises
var promise = new Promise(function(resolve, reject) {
// do a thing, possibly async, then…
if (/* everything turned out fine */) {
resolve("Stuff worked!");
}
else {
reject(Error("It broke"));
}
});
And here is how to use them
promise.then(function(result) {
console.log(result); // "Stuff worked!"
}, function(err) {
console.log(err); // Error: "It broke"
});
Check this link for more info
If you're using jQuery, you can use $.when
Example:
exmCall1 = $.getJson(..);
exmCall2 = $.getJson(..);
$.when(exmCall1, exmCall2).done(function (exmCall1Ret, exmCall2Ret) {
//do stuff
});
You can read the actual documentation here: http://api.jquery.com/jquery.when/
Or do some hardcode:
var running;
for (id in idsCollection) {
object.callService(id, function (res) {
collection.push(res);
running += 1;
});
}
var loop = setInterval(function() {
if(running >= idsCollection.length) {
filewriter.writetoFile("filename.json", JSon.Stringify(collection));
clearInterval(loop);
}
, 500);

Iterating on Cursor from MongoDB

I am trying to get all the documents in the collection, so I can do something based on them.
I am using the following code:
var test = pool.getDbCollection('Events');
test.find() //get them all
.each(function (error, doc) {
if (error) {
throw error;
} else {
//I am not getting here
//I am getting TypeError: Object 5 has no method 'each'
//And there are 5 Documents in the collection
}
});
}
And keep getting: Object 5 has no method 'each'
This function works just fine (same connection properties):
exports.getEventData = function (data) {
var deferred = Q.defer();
var eventCollection = pool.getDbCollection('Events');//TO DO Move this to config file
eventCollection.findOne({"id":data},
function (err, docs) {
if (!err) {
deferred.resolve(docs);
console.log('INFO(getEvents Method): Got the data !!!!')
} else {
deferred.reject('INFO(getEvents Method): Failed to get the data');
}
}
);
return deferred.promise;
};
It looks like each function is tried on the last object, but that last object is not in existance. at least it look to me that way. But I might be totally wrong.
doc will be null in the last iteration of the loop as a signal that the loop has completed.

Categories

Resources