Wait for Asynchronous javascript function - javascript

I've seen similar questions asked regarding this problem. I'm pretty new to javascript and I couldn't figure it out.
I have a function which calls another function.
sayHello() has an async call.
var hello_message = null;
function invokeSayHello(msg) {
sayHello(msg);
//next action
return hello_message;
}
function sayHello(msg) {
// simulate async call
setTimeout(function(){hello_message = msg + " World";},1000);
}
In this case hello_message is returned as null. How would I wait for that async call to complete before the next action line executes in invokeSayHello() function so the returned hello_message would not be null.
I think I'm supposed to use a callback but not sure how to do it.. Also, I call invokeSayHello() from a java file using executeScript()/Selenium
Appreciate all the help.

You should use the result inside the callback. You cannot/should not wait for the asynchronous function to complete. The asynchronous pattern assumes that you use the callback.
Like this:
function invokeSayHello(msg) {
sayHello(msg);
}
function sayHello(msg) {
// simulate async call
setTimeout(function(){
var hello_message = msg + " World";
// Here you can process the result, like alerting it for example or
// passing it to another function
alert(hello_message);
}, 1000);
}
So basically in asynchronous programming you forget about the keyword return and start passing callbacks to your javascript functions so that the caller can subscribe to those callbacks and whatever he wanted to do with the results inside the callback..

Related

How can one wait for a function to complete before the next function is called?

What is the best way to wait for a function to complete before the next function is called?
I have a scenario where two functions are called consecutively, one after the other. I need the first one to complete before the second one is called.
Function1();
Function2();
How do I tell the code to wait for Function1 to complete before attempting Function2?
WebDevelopment: solution can be javascript or jQuery, or Ajax based.
Thanks...
You can do many ways but a very simple Example
function first(){
// define every thing here and then at the end call your second function
function2();
}
Checkout more possibilities here
You could either use Promise or callback to solve this problem, with Promises being the more modern and cleaner way of doing things:
Promise:
function foo() {
return new Promise(function(resolve, reject) {
// do some work
resolve(optionalParam);
// something caused an error whoops
reject(optionalParam);
})
}
function bar() {
// do something
};
// Call bar only once foo finishes
foo().then(function() {
bar();
}, function() {
// this is the reject case an error here
});
Promises are able to be chained, meaning that if bar was a Promise we could chain another then event to that.
You could also use callbacks to solve your problem
function foo(cb) {
var data = 'alex';
cb(data);
}
function bar(name) {
// some processing
console.log(name);
}
// Call foo, then execute bar when foo finishes
foo(function(data) {
bar(data); // alex would be logged once the callback fires
});
In the callback example here, we pass a function as a parameter, once the running function block encounters your invocation of the cb parameter, it will invoke the function which emulates the asynchronousy. Just remember though that it does not stop the execution context on that function. If we had code like:
function foo(cb) {
var data = 'alex';
cb(data);
console.log('this is after so don't print it'); <-- still prints
};
The final console.log will print when the callback finishes its time on the event queue (unless of course you fire an even in CB like a http request, in which the log will fire and then the http request would finish after).
To stop the last console log you would need to explicitly tell javascript to return when cb is called to prevent further execution in that method, and personally this is where I favour Promises, once you resolve or reject the promise the execution context within that function scope is stopped.
if your in the browser, just use callback it's the easiest and cross-browser way to do it.
Exemple:
function sayBill() {
console.log('bill');
}
function sayHiAfterTwoSeconds(callback) {
setTimeout(function() {
console.log('hi');
// call the function you passed in parameter
if (typeof callback === 'function') {
callback();
}
});
}
sayHiAfterTwoSeconds(sayBill);
// will output 'bill hi'
https://jsfiddle.net/80bbbjco/
If you want better way to do it, but not cross browser there is promise : https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Promise
Or even more modern but not supported ATM async await: https://jakearchibald.com/2014/es7-async-functions/

How do you create custom asynchronous functions in node.js?

I was unsure how node.js was able to realize what functions where async and which were not and how to create a custom async function.
Say I wanted to create a custom asynchronous function. I would be surprised if just because I called my last argument to the async function callback or cb that it would just know its an async function:
function f(arg1, callback){
//do stuff with arg1
arg1.doStuff()
//call callback
callback(null, arg1.result());
}
I tried something like that and it did not work async. How do you tell node.js that f is actually async?
NOTE: this answer was written in 2014, before the existence of async function, and before Promises gaining popularity. While the same principles apply as well, I would recommend reading on Promises before trying to get your head around how they relate to "traditional" callback-driven async functions.
To create a function that calls its callback asynchronously, you have to use some platform-provided async primitive (typically IO-related) on it - timers, reading from the filesystem, making a request etc.
For example, this function takes a callback argument, and calls it 100ms after:
function asyncFn(callback) {
setTimeout(() => {
callback();
}, 100);
}
A possible reason for making a function async when it doesn't need to be, is for API consistency. For example, suppose you have a function that makes a network request, and caches the result for later calls:
var cache = null;
function makeRequest(callback) {
if (!cache) {
makeAjax(result => {
cache = result;
callback(result);
});
} else {
callback(cache);
}
}
The problem is, this function is inconsistent: sometimes it is asynchronous, sometimes it isn't. Suppose you have a consumer like this:
makeRequest(result => doSomethingWithResult(result));
doSomethingElse();
The doSomethingElse function may run before or after the doSomethingWithResult function, depending on whether the result was cached or not. Now, if you use an async primitive on the makeRequest function, such as process.nextTick:
var cache = null;
function makeRequest(callback) {
if(!cache) {
makeAjax(result => {
cache = result;
callback(result);
});
} else {
process.nextTick(() => callback(cache));
}
}
The call is always async, and doSomethingElse always runs before doSomethingWithResult.
Only native functions (with access to the event loop) are asynchronous. You would need to call one of them to get asynchronity for your callback. See What is a simple example of an asynchronous javascript function?.
If you aren't using any, there's hardly a reason to make your function asynchronous.

Callback function in node.js

I am new to node.js and relatively new to javascript. I have understood how callbacks works and wanted to try out a function myself. Here is my code:
MyScript.js:
var calledfunction = function()
{
console.log("This is a called function");
for(i=0;i<1090660;i++)
{
console.log(i);
}
console.log('done');
};
var sayHello = require('./sayhello.js');
objhello = new sayHello();
objhello.setupSuite(1,calledfunction);
console.log('Next statement;');
sayhello.js
var _ = require('underscore');
module.exports = exports = CLITEST;
function CLITEST(param1,param2)
{
}
_.extend(CLITEST.prototype, {
setupSuite: function (here,callback) {
console.log(here);
console.log('This is a callback function');
callback();
}
})
The above program is run by executing > node Myscript.js
My question is : the for loop consumes 50 secs to execute and print all the numbers in the console and then only executes the line "Next statement" which is outside the callback function .
Why is this happening? because I read theories saying that the immediate statements will be executed without having to wait for the function to get executed.
The ideal output should have been : print " Next statement" and then print the contents of the for loop
but in the above case it is vice versa ?
This is not a real callback, but rather a simple function call. Function calls are obviously synchronous, as the following statements may rely on their return values.
In order to may the callback async you can use: setTimeout or setImmediate, depending on the actual use case.
See also: Are all Node.js callback functions asynchronous?
As pointed out by one of the commenters, your code is executed in a synchronous fashion. The function calls are executed one after the other, thus no magic is happening and the console.log('Next statement;'); call is executed after the execution of the callback. If you were in a situation in which you had to call a function which executed an asynchronous call (i.e., an AJAX call with a callback) then yes, you would expect the subsequent console.log to be executed right after the asynchronous call.
In other words, in your case the code represents a simple function call, while an asynchronous call would offload the computation of the callback somewhere else, thus the execution of the code where the callback function was called keeps going by printing the statement and won't wait for the execution of the callback.

Why does this async.js series not behave synchronously

I'm attempting to use async.js to manage callbacks in an application. Below is an example of that code. However, I've run into a problem where the series of functions continues executing before one of the prior functions completes. For example, the resizeImage() function is still working when saveImageData() fires. But my intention is for the image to be saved only after it is resized. Shouldn't async.js handle this? If I have to pass a callback to resizeImage() what is the value of using async.js? Can someone show how using an async library is helpful in the example that I've given?
if (req.files) {
//removed some code not relevant to the question
async.series([
function (callback) {
model.saveImageData(tempPath, originalImage, s3Headers);
callback(null);
},
function (callback) {
var src = tempPath;
dst = path.dirname(tempPath) + "\\" + newImage;
model.resizeImage(src, dst);
callback(null);
},
function (callback) {
//the next function gets called before resizeImage() finishes executing
model.saveImageData(dst, newImage, s3Headers);
callback(null);
}
]);
}
Most likely saveImageData and resizeImage are non-blocking, asynchronous calls. Given they're doing I/O.
So you call resizeImage, it starts processing, returns control while it waits for IO, and your code immediately invokes the async.js callback that indicates that the function has finished it's work.
Instead, you should only call the async callback parameter after saveImageData and resizeImage complete, which means creating and using a callback function:
// this is just a guess at the api.
async.series[function(callback) {
model.resizeImage(src,dst,function() {
callback(null);
});
}];
You still have to ensure that the code inside each async function invokes the callback at the appropriate time.

JavaScript variable value

rpc.getUserInfo(function(result){
userdata = result;
}); //How can i get the value of "userdata"?
I try:
var userdata = "";
rpc.getUserInfo(function(result){
userdata = result;
});
alert(userdata); // it's "undefined"
Time for some assumptions:
RPC usually stands for Remote Procedure Call
This suggests you are performing Ajax
A standard pattern for Ajax functions is to accept a callback function which runs when the call is complete.
Ajax is Asynchronous, so you can't make an Ajax call, wait for the response, then run the next line of the function that made the call.
Rewrite the script so that whatever you want to do when the Ajax data comes back is done in the callback and not in the function that makes the call (which is where it is now).
Wrong:
var userdata = "";
rpc.getUserInfo(function(result){
userdata = result;
});
alert(userdata);
Right:
rpc.getUserInfo(function(result){
alert(result);
});
You haven't said, but I'm guessing that getUserInfo involves an asynchronous ajax call. That being the case, you can't use the value inline, you can only use it in the callback. E.g.:
rpc.getUserInfo(function(result){
var userdata;
userdata = result;
alert(userdata);
});
You just put all of the logic that you would have put after the getUserInfo call inside the callback instead. That sounds difficult or awkward, but with JavaScript it's trivially easy:
function doSomething() {
var foo;
// Do some setup
foo = 42;
// Here's our first asynchronous call; like all good asynchronous calls,
// it accepts a function to call when it's done
triggerAjaxCall("mumble", function(bar) {
// Now the first call is complete, we can keep processing
// Note that we have access to the vars in our enclosing scope
foo += bar;
// Need to do another asynchronous call
triggerSomeOtherAjaxCall(foo, function(nifty) {
// Now the second call is complete and we can keep working with
// all of our stuff
alert("foo: " + foo + "\n" +
"bar: " + bar + "\n" +
"nifty: " + nifty);
});
});
}
Note that doSomething returns before the first callback is called.
Obviously the anonymous functions above are only appropriate if they're an intrinsic part of doSomething; otherwise, move their functionality into separate named functions.

Categories

Resources