How can i access variable inside callback nodejs? - node.js

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.

Related

nodejs call two class functions synchronous

I have two class functions in nodejs and I want to call both synchronously both one after another.
var questionData = questionModelObj.getQuestionbyId(req.params.id);
var answerData = answerModelObj.getAnsByQuesId(req.params.id);
Here questionModelObj take time to execute and it calls answerModelObj without completing questionModelObj. It results answerData overwrites the questionData.
Please suggest how to call these two functions one after another(synchronous) and explain.
One option is to execute the second function as a callback to the first. This is pretty standard for Javascript.
// Declare variable to hold response
var answerData;
var questionData = questionModelObj.getQuestionbyId(req.params.id, function() {
// This is the callback function
answerData = answerModelObj.getAnsByQuesId(req.params.id);
}
The function signature of getQuestionbyId would then need to take in 2 parameters, the second being a function to be called later on:
questionModelObj.getQuestionbyId = function(id, callback) {
// Do things with the id
callback();
}
The callback function is then called after getQuestionbyId is done.

Trying to understand node.js callback when the function normally doesn't expect any parameters?

I am trying to work with node.js and node-java and trying to get my head wrapped around some concepts, and in particular how to write async method calls.
I think that, for a function in Java, myclass.x():
[In Java]:
Z = myclass.x(abc);
And:
[In node.js/node-java]:
myclass.x(abc, function(err,data) {
//TODO
Z = data;});
In other words, the myclass.x function gets evaluated using the parameter abc, and if no error, then the result goes into "data" which is then assigned to Z.
Is that correct?
Here's the thing (or one of the things) that I am confused about.
What happens if the function myclass.x() doesn't take any parameters?
In other words, it is normally (in Java) just called like:
Z = myclass.x();
If that is the case, how should the node.js code look?
myclass.x(, function(err,data) {
//TODO
Z = data;});
doesn't seem right, but:
myclass.x( function(err,data) {
//TODO
Z = data;});
also doesn't seem correct.
So what is the correct way to code the node.js code in this case?
Thanks in advance!!
Jim
EDIT 1: Per comments, I'm adding the specific code I'm working with is the last couple of commented out lines from this other question at:
node.js and node-java: What is equivalent node.js code for this java code?
These are the lines (commented out in that other question):
var MyFactoryImplClass = java.import("oracle.security.jps.openaz.pep.PepRequestFactoryImpl.PepRequestFactoryImpl");
var result = myFactoryImplClass.newPepRequest(newSubject, requestACTIONString ,requestRESOURCEString , envBuilt)
I tried to make the last line use an async call:
MyFactoryImplClass.getPepRequestFactory( function(err,data) {
//TODO
pepReqF1=data;})
javaLangSystem.out.printlnSync("Finished doing MyFactoryImplClass.getPepRequestFactory() and stored it in pepReqF1 =[" + pepReqF1 + "]");
But the output was showing the value of that pepReqF1 as "undefined".
If calling the method with one parameter and a callback is:
myclass.x(abc, function(err, data) {
// ...
});
Then calling a method with only a callback would be:
myclass.x(function(err, data) {
// ...
});
The function(err, data) { } part is just a normal parameter just like abc. In fact, you can pass a named function with:
function namedFun(err, data) {
// ...
}
myclass.x(abc, namedFun);
Or even:
var namedFun = function (err, data) {
// ...
}
myclass.x(abc, namedFun);
Functions in JavaScript are first-class objects like strings or arrays. You can pass a named function as a parameter to some other function:
function fun1(f) {
return f(10);
}
function fun2(x) {
return x*x;
}
fun1(fun2);
just like you can pass a named array:
function fun3(a) {
return a[0]
}
var array = [1, 2, 3];
fun3(array);
And you can pass an anonymous function as a parameter:
function fun1(f) {
return f(10);
}
fun1(function (x) {
return x*x;
});
just like you can pass an anonymous array:
function fun3(a) {
return a[0]
}
fun3([1, 2, 3]);
There is also a nice shortcut so that instead of:
fun1(function (x) {
return x*x;
});
You can write:
fun1(x => x*x);
Making my comment into an answer...
If the issue you're experiencing is that Z does not have the value you want when you are examining it, then that is probably because of a timing issue. Asynchronous callbacks happen at some unknown time in the future while the rest of your code continues to run. Because of that, the only place you can reliably use the result passed to the asynchronous callback is inside the callback itself or in some function you would call from that function and pass it the value.
So, if your .x() method calls it's callback asynchronously, then:
var Z;
myclass.x( function(err,data) {
// use the err and data arguments here inside the callback
Z = data;
});
console.log(Z); // outputs undefined
// you can't access Z here. Even when assigned
// to higher scoped variables because the callback has not yet
// been called when this code executes
You can see this is a little more clearly by understanding the sequencing
console.log('A');
someAsyncFucntion(function() {
console.log('B');
})
console.log('C');
This will produce a log of:
A
C
B
Showing you that the async callback happens some time in the future, after the rest of your sequential code has executed.
Java, on the other hand, primarily uses blocking I/O (the function doesn't return until the I/O operation is copmlete) so you don't usually have this asynchronous behavior that is standard practice in node.js. Note: I believe there are some asynchronous capabilities in Java, but that isn't the typical way things are done and in node.js, it is the typical ways things are done.
This creates a bit of an architectural mismatch if you're trying to port code that uses I/O from environment from another because the structure has to be redone in order to work properly in a node.js environment.

For loop in redis with nodejs asynchronous requests

I've got a problem with redis and nodejs. I have to loop through a list of phone numbers, and check if this number is present in my redis database. Here is my code :
function getContactList(contacts, callback) {
var contactList = {};
for(var i = 0; i < contacts.length; i++) {
var phoneNumber = contacts[i];
if(utils.isValidNumber(phoneNumber)) {
db.client().get(phoneNumber).then(function(reply) {
console.log("before");
contactList[phoneNumber] = reply;
});
}
}
console.log("after");
callback(contactList);
};
The "after" console log appears before the "before" console log, and the callback always return an empty contactList. This is because requests to redis are asynchronous if I understood well. But the thing is I don't know how to make it works.
How can I do ?
You have two main issues.
Your phoneNumber variable will not be what you want it to be. That can be fixed by changing to a .forEach() or .map() iteration of your array because that will create a local function scope for the current variable.
You have create a way to know when all the async operations are done. There are lots of duplicate questions/answers that show how to do that. You probably want to use Promise.all().
I'd suggest this solution that leverages the promises you already have:
function getContactList(contacts) {
var contactList = {};
return Promise.all(contacts.filter(utils.isValidNumber).map(function(phoneNumber) {
return db.client().get(phoneNumber).then(function(reply) {
// build custom object
constactList[phoneNumber] = reply;
});
})).then(function() {
// make contactList be the resolve value
return contactList;
});
}
getContactList.then(function(contactList) {
// use the contactList here
}, funtion(err) {
// process errors here
});
Here's how this works:
Call contacts.filter(utils.isValidNumber) to filter the array to only valid numbers.
Call .map() to iterate through that filtered array
return db.client().get(phoneNumber) from the .map() callback to create an array of promises.
After getting the data for the phone number, add that data to your custom contactList object (this is essentially a side effect of the .map() loop.
Use Promise.all() on the returned array of promises to know when they are all done.
Make the contactList object we built up be the resolve value of the returned promise.
Then, to call it just use the returned promise with .then() to get the final result. No need to add a callback argument when you already have a promise that you can just return.
The simplest solution may be to use MGET with a list of phone numbers and put the callback in the 'then' section.
You could also put the promises in an array and use Promise.all().
At some point you might want your function to return a promise rather than with callback, just to stay consistent.
Consider refactoring your NodeJS code to use Promises.
Bluebird is an excellent choice: http://bluebirdjs.com/docs/working-with-callbacks.html
you put async code into a for loop (sync operations). So, each iteration of the for loop is not waiting for the db.client(...) function to end.
Take a look at this stackoverflow answer, it explains how to make async loops :
Here

Node tutorial - LearnYouNode - Juggling Async - using nested callbacks

I was trying to solve the "Juggling Async" problem in the "learnyounode" workshop from nodeschool.io. I saw a lot of questions here about this problem where it is not working because the url's were being called from a loop. I understand why that wouldn't work.
I had tried something like this.
var http=require('http');
console.log(process.argv[2],process.argv[3],process.argv[4]);
fn(process.argv[2],
fn(process.argv[3],
fn(process.argv[4])));
function fn(url,callback){
http.get(url,function(response){
var string='';
response.setEncoding('utf8');
response.on('data',function(data){
string+=data;
});
response.on('end',function(){
console.log(url,string);
if (callback) {
callback();
}
});
});
};
As per my understanding, the second GET call should go out only after the first one has ended, since it is being initiated after response end. But the output is always in different order.
I have seen the correct solution. I know that doing it this way fails to leverage the advantage of async, but shouldn't the callbacks make it output in order?
When you pass in a function as a callback, you need to only pass in the function name or function definition. By providing the arguments, you are actually calling the function.
E.g. let's say you had a function f1 that took in another function as a parameter, and another function f2 that you want to pass into f1:
function f1(func_param) {
console.log('Executing f1!');
}
function f2(a_param) {
console.log('Executing f2!');
}
When you do the following call (which is similar to what you are doing, providing a callback function and specifying parameters for the callback):
f1(f2(process.argv[2]));
You're evaluating f2 first, so 'Executing f2!' will print first. The return of f2 will get passed as a parameter into f1, which will execute and print 'Executing f1!'
In your call
fn(process.argv[2],
fn(process.argv[3],
fn(process.argv[4])));
You are saying, let's pass the result of fn(process.argv[4]) as a callback to fn(process.argv[3]), and we'll get the result of calling that and pass that as a callback to fn(process.argv[2]).

Is return will work fine in node.js in normal functions without IO Operations?

My function is like this for examle
function summ(a,b)
{
return a+b;
}
module.exports.summ = summ;
in other file:
var obj = require('./that file')
function app()
{
var s = obj.summ(7,7);
}
if i put console.log(s);
it is giving answer perfect.
My doubt is this will come all the time when request is coming frequently since i m using this kind of return in rest api ?
Or call back function is required like that result is
function summ(a,b,callback)
{
callback(a+b);
}
and
function app()
{
obj.summ(7,7,function(result){
var s = result;
}
}
As long as your summ function behaves in a synchronous manner, like it does in your example code, you don't have to use callbacks.
If you would use asynchronous functions in summ (anything I/O related, like reading a file, querying a database, opening a network connection), that would require passing a callback function because you would have to wait until the action is completed before you return the result (by calling the callback function).

Resources