Node Async Method Understanding - node.js

I have a method that I want to finish before any code after it can be ran but am lost in understand external links when is comes to this.
In one method I have the following code
var x = someMethod("1","2","3"); // Finish before anything below can be ran
The method itself is simple
function someMethod(x,y,z){
if(1){
return "sdfh"
} else if(2){
return "asdf"
} else {
return "ljkk"
}
}
How can I retrieve x before continue the code below it. Ive seen examples of nested functions, await, async but am lost

Try:
const someMethod = (x, y, z) => {
...
};
const otherMethod = async () => {
let x = 'before value';
console.log(`before someMethod x: ${x}`);
// Finish before anything below can be ran
x = await someMethod("1", "2", "3");
console.log(`after someMethod x: ${x}`);
};
Basically you are defining the function which has the await call as an asynchronous function using the async keyword in the function declaration - and can signify the portion of the code which you would like to wait by prepending with await. There are nuances to this - but hopefully this helps.

Java script is single thread and synchronous. I recommend checking out JavaScript promises. However I would assume your code executes synchronously until it hits something like a AJAX that is asynchronous.
check this answer out:
When is JavaScript synchronous?.

Related

Basic node.js - variable and Mongoose scope

the console.log(workingWeekdaysVar) line; is outside the findOne's scope, and the variable was declared outside it too, yet it's giving me null ...
when i put console.log(workingWeekdaysVar); inside the findOne's scope, it does give the right output, but this is useless for me because I wanna use workingWeekdaysVar elsewhere below.
The two commented out lines are the 2nd approach i attempted to do, but it gave me an undesirable output because this whole code is inside a complicated for loop.
How can I simply pass the fetched value of workingWeekdaysVar out of the scope?
var workingWeekdaysVar = [];
buyerSupplierFisModel.findOne(filter).then(function (combo) {
workingWeekdaysVar = combo.workingWeekdays;
//server.getWorkingWeekdays = function () { return combo.workingWeekdays };
});
console.log(workingWeekdaysVar);
//console.log(server.getWorkingWeekdays());
findOne() is an asynchronous function (it returns a promise object). This means that it returns inmediately and your next code line is run (in this case, console.log(workingWeekdaysVar);. But, since the function isn't done yet, workingWeekdaysVar is empty, and it will be empty until findOne() has done its job and returned the results in the provided chained callback .then(function (combo) {....
So if you want to do anything with the results, you'll have to do it in the callback. One option to this would be to use async / await:
(async () => {
try {
const { workingWeekdaysVar } = await buyerSupplierFisModel.findOne(filter)
console.log(workingWeekdaysVar)
} catch (e) {
console.log(`Error: ${e}`);
}
})()
Re-arranging your code a bit:
let doToResponse = (combo)=>{
workingWeekdaysVar = combo.workingWeekdays;
console.log(workingWeekdaysVar);
}
buyerSupplierFisModel.findOne(filter).then(function (combo) {
doToResponse(combo)
});
good for re-usability
My personal favorite:
buyerSupplierFisModel.findOne(filter).then(combo=> {
workingWeekdaysVar = combo.workingWeekdays;
console.log(workingWeekdaysVar);
});
The important thing is keep in mind, as Miguel Calderón says.. findOne - returns a promise. At that point you have another thread with different local (Lexical?) scope

How to export async function?

following is my code -
abc.js
class abc {
async foo1() {
// do something
return result;
}
async foo2() {
// do something
return result;
}
module.exports = abc
}
another-file.js
const abc = requir(./abc);
abc.foo1();
// this results in error
// TypeError : abc.foo1 is not a function
How should I do this?
Several points. By convention class names starts with capital letter. Your problem has nothing to do with async functions. You have 2 options to solve this problem. First option is to make your function static. Then you can use it directly without instance. Second option is just call it differently: instantiate class first to get instance, and then call your method on this instance.
And also keep in mind, that await keyword can be used only inside other async function. And you need await keyword if you want to handle promise, returned by async function (it returns promise of result, not result)

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.

Node return yielded value from Q.async

With this piece of code :
function * foo(ctx) {
// process some things
// yield some async stuff...
return 'foo';
}
Q.async(function * (ctx) {
return yield foo(ctx);
})(this).done(function(result) {
console.log(result);
});
I expected result to be the result of foo() (i.e. 'foo'), but it is rather the actual generator object!
What am I missing or don't I understand here?
** Solution **
While the answers are good solutions, I figured that I could even shorten the whole thing by simply doing
result = Q.async(foo)(this);
async is a generator function decorator. Any function that you intend to use as a promise trampoline must be decorated. Also, I have elected to pass the this context as this.
var foo = Q.async(function *() {
// yield, yield, yield
return "foo";
});
var bar = Q.async(function *() {
// yield, yield, yield
return foo.call(this);
});
bar.call(this).done(function (result) {
console.log(result);
});
The main issue is that you need to do this instead:
return yield* foo(ctx);
What you had previously was calling return yield foo(ctx). That will do foo(ctx) to create a generator, then yield ... will yield the generator. Since the generator isn't a promise, Q will consider it resolved and make the yield result in a generator. Then the result of the yield is returned, so the async function results in a generator object. By adding the *, you tell the generator to take over rather than yield, and thus the result of yield* foo(ctx) is actually foo instead of a generator returning foo.
The second problem I ran into locally (which you may not if you have actual async code in foo) is that if the foo generator is synchronous instead of asynchronous, it appears to return foo immediately instead of returning a promise that resolves to foo, so the .done function does not exist.

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