Node.js Async Waterfall Hangs - node.js

I am currently implementing an API built using Express.js, following the MVCS pattern for my design. After reading about the Async module, I came to the conclusion that it would be a good idea for me to take advantage of its powerful methods. Unfortunately, I am running into a problem I can't seem to fix, and was wondering if someone could give me some advice. Let's take look at the code:
'use strict'
_ = require 'lodash'
async = require 'async'
validator = require 'express-validator'
class BaseService
constructor: (#model, #relationships, #fields) ->
list: (req, callback) ->
async.waterfall [
validate(req).bind(this),
query.bind(this)
], callback
validate = (request) ->
valid = request
(next) ->
next null, valid
return
query = (valid) ->
query = #model.find({})
if valid.query.q
query = query.where(valid.query.q)
if valid.query.sort
query = query.sort(valid.query.sort)
if valid.query.select
query = query.select(valid.query.select)
# Requests hangs at this point. Any ideas why?
(next) ->
query.exec next
return
module.exports = BaseService
Basically, I would like to first validate the query string that was passed with the request. Then, a Mongoose query is built depending on whether certain fields are present or not in the validated object. Lastly, it should execute the query and pass the results to the callback function. Here my implementation fails as it hangs, and the callback is never executed. I commented the line in the code snippet, to give you all a better idea of what is going on.
Can someone please point me in the right direction?

Your main problem is your query method signature needs to accept a callback as the last argument.
query = (valid, callback) ->
For waterfall, the first worker function takes (callback), but the rest of them take (previousResult, callback).
Also, given how you are using your query method, it does not need to return a function as you have it doing. Just accept the callback as an argument and invoke it when ready to move on to complete the waterfall.
Aside: using "query" for both a method and a local variable in a coffeescript class is error prone and confusing. Use a different name for the local variable such as "modelQuery".

Related

How to pass data in a promise chain, I am using sequelize

I am really struggling here. Admittedly I am no guru especially when it comes to node and asynchronous programming, I am an old C# .net developer so I am comfortable with code but struggling here.
Here's the back story, short and sweet. I have a pg database and I am using the sequelize ORM tools to create a relatively simple CRUD app.
Here's what I want to do.
Make a call to the findAll function on one object.
I need a piece of information from that first call so that I can make a subsequent call.
For instance. Lookup the current user to get their details, grab their ID and now lookup their display preferences.
I know I can run two requests that are not linked using Promise.all, here is an example of this already working.
var delConfig = deliverabiltyConfigs.findAll2(req.signedCookies.tsUser);
var delPack = deliverabilityPackages.findAll2();
Promise.all([delConfig, delPack]).then((results) =>{
res.render('index', { title: 'Deliverability Calculator', UserEmail : req.signedCookies.tsUser, UserName : req.signedCookies.tsUserName, data:results[0], packs:results[1]});
});
Where I am stuck is passing data from one promise to then next and needing them to run asynchronously.
Please help!
There are a few way you can do this. Either use promise chaining or with async & await.
Promise chaining might be the simplest way to do this now, but I would suggest using async await as its easier to read. Since you didn't really provide a sample of what you were trying to do I will make something generic that should hopefully help.
So using promise chaining you would do something like:
pgConnection.findAll().then((data) => {
const foo = data.foo;
pgConnection.findSomething(foo).then((data2) => {
console.log(data2);
});
});
What is happening here is once the promise from findAll() is resolved successfully it will call the .then method and will pass the resulting data there for you to use in your next db query and then I am just printing out the result of the final db query.
This is how you could do it using async & await:
async function getFoo() {
const data = await pgConnection.findAll();
const foo = data.foo;
const data2 = await pgConnection.findSomething(foo);
console.log(data2);
}
The await keyword can only be used inside of an async function so it might not be as simple to change as just using a .then promise chain.

Nodejs Callback: How to define a Callback?

I am reviewing a sample nodejs server code, which is working fine. but could not understand the following code:
var handlers = {};
// Creating a sample handler
handlers.sample = function(data,callback){
callback(406,{'name':'sample handler'}); // How is this line of code working??
};
// Creating a not found handler
handlers.notFound = function(data,callback){
callback(404); // How is this line of code working??
};
In the entire code there is no implementation of "callback" function then how
callback(406,{'name':'sample handler'});
and
callback(404);
are working?
Please suggest. Thanks.
callback isn't implemented in the code you posted; it's a named parameter.
To call one of the functions that requires a callback, you'll need to pass it in as an argument, like:
handlers.sample("some data", () => console.log("I'm in a callback!));
The first argument ("some data") goes in the data parameter, and the second argument (() => console.log("I'm in a callback!)) goes in the callback parameter. When callback(404) is run, it executes the callback function (in the above example, it would do console.log("I'm in a callback!)).
Basically, when you call handlers.sample, you should pass a function as your second argument, and that function will be called, usually asynchronously, and presumably after something is done with the data you pass as the first argument. For example, based on the code you provided:
handlers.sample(dataObject, (number, object) => {
console.log(number)
console.log(object.name)
})
would yield this result in the console:
406
sample handler
I’m curious if this is a public library you are seeing this code in, so we can take a closer look?
I did a further digging in into this and found that
selectedHandler
in the following code (this is not mentioned in the question) is getting resolved into handlers.sample or handlers.notFound variable names based on some logic (which is not mentioned here)
selectedHandler(data,function(status,payloadData){
// somelogic with the status and payloadData
});
And second parameter of this function which is a complete function in itself
function(status,payloadData){
// somelogic with the status and payloadData
}
is going as the second parameter in handlers.sample or handlers.notFound which is a Callback. So execution of Callback in the current context is execution of this function (this function is anonymous because it has no name and getting executed as Callback)

How can i access variable inside callback nodejs?

I'm unable to get the values in meals object although i have create new object at the top can any one tell which is the best procedure access variable inside callback function
var meals = new Object();
passObj.data = _.map(passObj.data, (x)=> {
x.mealImageUrl = !_.isNull(x.image_url) ? `${config.image_path}${x.image_url}` : x.image;
dbHelpder.query(`select * from meals where meal_category = ${x.category_id}`,(error,result)=>{
meals = x.result;
passObj.total = 555
});
return x;
});
You need to use callback again inside the callback function. :)
You are doing something asynchronous, it means, there are no sequence codes. (At least, I keep this in my mind, don't know how others think about this.) So, the code should be:
function somehow(callback) { // you get the result from callback
var meals = new Object();
passObj.data = _.map(passObj.data, (x)=> {
dbHelpder.query(`select * from meals where meal_category = ${x.category_id}`,(error,result)=>{
meals = x.result;
passObj.total = 555;
callback(meals); // Here you get the result
});
}
return x;
}
So, when you are going to use this function, it should be
function afterMeals(resultMeals) {
// do something on the meals
}
somehow(afterMeals);
Use some other technology can make it a bit clear (like promise), but you can not avoid callback actually.
First of all, I cannot see what passObj exactly is, apparently it is defined elsewhere.
Secondly, callback functions don't function the way you seem to think they do. Typically one reason to use them is to implement asynchronous calls, so returning a value is not of use.
The idea is as follows. Usually you have a call like this:
var myFunc1 = function(){
return 42;
}
var x = myFunc1();
myFunc2(x);
However when myFunc1 is an asynchronous call returning a value is impossible without using some sort of promise, which is a topic on its own. So if myFunc1 was an asynchronous call and the 42 was returned e.g. by a server, then just returning a value caused the value to be null, because the return value is not calculated and received yet, when you arrive at return.
This is a reason for callbacks to be introduced. They work in a way, that allows for asynchronous calls and proceeding the way you want to after the call has finished. To show on the example above:
var myFunc1 = function( myFunc2, params ){
// do async stuff here, then call the callback function from myFunc1
...
myFunc2(x);
}
So the asynchronous function doesn't return anything. It makes the calls or calculations it needs to make and when those are done (in the example that is when x has been declared and assigned a value) myFunc2, which is the callback function in our example, is called directly from the asynchronous function.
Long story short - do what you need to do with x directly inside the callback function.

Mongoose - Whats the difference between find({},cb) and find({}).exec(cb)?

I found 2 ways to execute queries using mongoose find(), but was wondering if they are different:
When should we use:
Model.find({},cb)
And when should we use:
Model.find({}).exec(cb)
Both execute the query and then run the callback.
The main difference is that the first one, returns a Query object while the second returns a Promise which is useful if you need promises.
const query = Model.find({}, cb);
Then you can work with the query variable.
While the promise...
const promise = Model.find({}).exec();
Then you can work with the promise and do things like:
promise.then(cb);
promise.catch((err) => {
console.error(err);
});
But if you do Model.find({}).exec(cb); the callback is also called without using promises...
I hope it helps
The difference is that the first one executes the query and calls your callback. Whereas in the second one where you omit the callback, the query will not be executed. Instead it will return a Query object which can be used to chain methods, specify search terms, and cursor options, etc...
http://mongoosejs.com/docs/2.7.x/docs/query.html
If you don't need to do any kind of chaining, or anything else with the underlying Cursor then just use the first method.
But the second method can be helpful to do things like:
findCars : function(options, callback) {
var query = Model.find({});
if(options.limit) query.limit(options.limit);
if(options.skip) query.limit(options.skip);
if(options.populate) query.populate(options.populate);
return query.exec(callback);
}

how to use q promises?

I have two mongoose models that control mongo actions for each model. from an index route I am calling a function from one of my models I want to call a function from my other model when the first one finishes.
Assume the following:
ThingOneSchema = new Schema({ _id :String, name :String});
ThingOneSchema.statics.saveUser = function(thing, callback){
...do some stuff
ThingTwoSchema = new Schema({_id :String, property:String});
ThingTwoSchema.statics.doSomething = function(prop, callback){
... do some stuff
In my calls from index I would like to call doSomething from thingTwoSchema and then saveUser from ThingOneSchema. I find Q kinda confusing when trying to apply it in my program. Often examples take the form of doSomething(result).then(function(result))
but I faile to see how q is invoked this way.
If you would like to chain the promises as following
doSomething(res).then(function callback(res) {
//some stuff again
})
Make sure function doSomething return a promise.
function doSomething (res) {
//do stuff..
return Q(some_result);
}
Then, your callback which passed to then will be called with arguments some_result later on.
If your async operations are callback based instead of promise based, make sure you have checked out deferred. It allows you to wrap those async calls with Q promise.
Here is another bunch of examples which captures common problems when dealing with promise.

Resources