I have a problem with the code below. Everything goes fine, until the db.collection.update.
At at console.log(n.6), the callback is not consider as a function anymore. And I don't understand why.
The console display:
callback(errorCode404)
TypeError: object is not a function
var newData = req.body;
...
async.waterfall([
function(callback){
console.log('n3');
db.getConnection(callback);
},
function(db, callback){
console.log('n4');
db.collection('dossiers', callback);
},
function(dossiers, callback){
console.log('n5');
dossiers.update({'_id': mongodb.ObjectID(id)}, {$set:newData}, callback);
},
function(result, callback){
console.log('n6');
if(result != 1) {
console.log('n6.1');
callback(errorCode404);
}
console.log('n6.2');
callback(null, 'Dossier mise a jour.');
}
], function(err, result){
...
});
Can someone clarify me about this?
What's happening is that the update callback has three parameters: error (if any), the count of records that were modified, and a status object. waterfall handles the error parameter, but the last two are passed as parameters to the subsequent waterfall function (n6), with the callback being provided as the third parameter, not the second.
So you need to change that part of your code to be something like:
...
function(dossiers, callback){
console.log('n5');
dossiers.update({'_id': mongodb.ObjectID(id)}, {$set:newData}, callback);
},
function(numModified, status, callback){
console.log('n6');
...
Related
I learn Node.js and doing a small site guided by MDN.
I reached to place where there using module async.
This is code
async.parallel({
book_count: function(callback) {
Book.countDocuments({}, callback); // Pass an empty object as match condition to find all documents of this collection
},
book_instance_count: function(callback) {
BookInstance.countDocuments({}, callback);
},
book_instance_available_count: function(callback) {
BookInstance.countDocuments({status:'Available'}, callback);
},
author_count: function(callback) {
Author.countDocuments({}, callback);
},
genre_count: function(callback) {
Genre.countDocuments({}, callback);
}
}, function(err, results) {
res.render('index', { title: 'Local Library Home', error: err, data: results });
});
};
This code count number documents in the database.
I don't understand what is argument "callback". There have nothing sent in these properties "book_count, book_instance_count, author_count, etc.." but all of these function work excellent.
Please, explain to me , what is odd argument "callback" and how to use it.
Callback function
A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.
function greeting(name) {
alert('Hello ' + name);
}
function processUserInput(callback) {
var name = prompt('Please enter your name.');
callback(name);
}
processUserInput(greeting);
https://developer.mozilla.org/en-US/docs/Glossary/Callback_function
I have variable number of async function to run. For two function, I can write like this:
async.parallel([
function(parallelCb) {
client.get('statuses/user_timeline', {screen_name: 'rajeevnodetest'}, function(error, tweets, response){
parallelCb(null, {error: error, tweets: tweets});
});
},
function(parallelCb) {
client.get('statuses/user_timeline', {screen_name: 'rajeev_jayaswal'}, function(error, tweets, response){
parallelCb(null, {error: error, tweets: tweets});
});
},
], function(error, results) {
// results will have the results of all 2
res.send(JSON.stringify(results));
});
How should I call variable number of function inside async.parallel ? I tried adding for loop inside async.parallel but it did not work. Any suggestion ?
I am assuming you will be reaching same api in order to retrive user tweets.
Therefore you have an array containing all tweeter handles:
var screenNames = ['rajeevnodetest', 'rajeev_jayaswal', ..., 'brandnewhandle'];
You can define a function to reach the API like this:
//Custom function to find user status list
var findStatus = function(handle, callback) {
client.get('statuses/user_timeline', {screen_name: handle}, function(error, tweets, response){
callback(null, {error: error, tweets: tweets});
});
}
Then you could use Asyn.map function in order to execute that function once for every element in your tweeter handle list like:
async.map(screenNames, findStatus, function(err, results) {
// results will have the results of all 2
res.send(JSON.stringify(results));
});
If you need to make calls to multiple API endpoints for each tweeter handle then you would need to use paralell and create an entry for each endpoint.
You can use async.times function Like this
function(parallelCb) {
async.times(50, function (n, next) {
client.get('statuses/user_timeline', {screen_name:'rajeevnodetest'},
function(error, tweets, response){
next(err, tweets);
});
}, function (error, results) {
// do something with your results
parallelCb(null, {error: error, tweets: results});
}
}
So if you want to Run n number of async function before calling another method You will have to use async.series method using async.times in it because according to async.parallel documentation it Run the tasks collection of functions in parallel, without waiting until the previous function has completed.
you should look into EventEmitter
call the emit method withing your async functions and hook all the function you want to run to that event name
I am making a code calling APIs using async.parallel
But sometimes API (i.e., cd.ChartData or ob.OrderBook in my code) returns error.
In that case, I want to repeat to call both of APIs even if only one API returns error.
How to do it?
async.parallel([
function(callback){
cd.ChartData(pair,end,days,function(ChartData){
callback(null,ChartData);
},
function(callback){
ob.OrderBook(pair, depth, function(OrderBook){
callback(null,OrderBook);
});
}
],
function(err, results){
})
module.exports.ChartData = function(pair, end, days, callback){
request.get(url, function(error, response, body){
if (error) {
callback(error);
} else {
ChartData = JSON.parse(body);
callback(ChartData);
}
});
};
We can use recursive function.
*** Please note that this pattern will cause the function to loop indefinitely when there is error from request.get so you might want to limit the times of retry.
//let's change your callback to standard Node.js callback format, callback(error, result)
//the first parameter to callback should always be null when there is no error but don't skip it
module.exports.ChartData = function(pair, end, days, callback) {
request.get(url, function(error, response, body){
if (error) {
console.error(error);
exports.ChartData(pair, end, days, callback); //keep trying if error occurs
} else {
ChartData = JSON.parse(body);
callback(null, ChartData);
}
});
};
I'm calling a mongodb query and need to assign the result to a value.
function oneref(db, coll, cb) {
var pipeline = [{ "$sample": { size: 1 } }]
var ohoh
coll.aggregate(pipeline, function (err,oneref) {
ohoh=oneref[0].code
})
console.log('hoho?: ' + ohoh)
cb(null, db, coll)
},
I understand I have an issue understanding callback, but even checking all hello world examples, I'm struggling.
How to write it in the simplest way so I only assigne the var hoho when the query finished?
Thanks a lot in advance.
You're getting undefined value for the variable hoho is because the aggregate() cursor method is asynchronous, and can finish at any time. In your case, it is finishing after you're using console.log(), so the values are undefined when you're accessing them.
Asign the variable as the argument to the callback within the aggregate() function callback i.e.
function oneref(db, coll, cb) {
var pipeline = [{ "$sample": { size: 1 } }];
coll.aggregate(pipeline, function (err, oneref) {
if (err) return cb(err);
var hoho = oneref[0].code
console.log('hoho?: ' + hoho);
cb(null, hoho);
});
};
Calling the oneref function:
oneref(db, collection, function(err, result){
console.log(result); // logs the oneref[0].code
});
Refer to this Question for a better understanding on how callback functions work.
I have functions in different place.(this is common function it will use many place.
So I tried to call the function using async parallel but its not working.
I attached the my code following:L
var userId = 33;
async.parallel({
video(userId, callback) {
callback(null, callback);
},
video1(userId, callback) {
callback(null, callback);
}
}, function(err, results) {
console.log(results);
});
function video (userId, callback) {
client.query("select youtube_id,title,id,thumbnail,search_item from resource order by random() limit 1 ", function(err, video) {
callback(err, video);
});
}
function video1(userId, callback) {
client.query("select youtube_id,title,id,thumbnail,search_item from resource1 order by random() limit 1 ", function(err, video1) {
callback(err, video1);
});
}
The {fnName()} syntax is a function declaration. You want to use a function call ... in fact you can just use async.parallel({video, video1}, (err, results) => console.log(results) to achieve the same effect... except that you also need to pass in userId. So what you actually intend is to call the function rather than declare it:
async.parallel([
callback => video(userId, callback),
]);
You need to pass function references to async.parallel() and you need to pass an array, not an object. You want the code to have this form:
async.parallel([fn1, fn2], finalCallback);
See the async.parallel() doc here for specific examples of the syntax you want to use.
Where fn1, fn2 and finalCallback are all function references that can be called by the async.parallel() infrastructure, not something you call yourself.
Change your code to this:
async.parallel([
function(callback) {
client.query("select youtube_id,title,id,thumbnail,search_item from resource order by random() limit 1 ", function(err, video) {
callback(err, video);
}),
},
function(callback) {
client.query("select youtube_id,title,id,thumbnail,search_item from resource order by random() limit 1 ", function(err, video1) {
callback(err, video1);
});
}
], function(err, results) {
console.log(results);
});
Presumably, your two database queries should be different somehow (your code showed them identical).
If your functions are already defined somewhere, then you can pass an anonymous function reference that will call them. You need to do this if your functions don't have the exact same calling convention that async.parallel() requires. You can do that like this:
async.parallel([function(callback) {
video(userId, callback);
}, function(callback) {
video1(userId, callback);
}], function(err, results) {
console.log(results);
});