How to Wait for a Function to Finish in JavaScript
-
Sync
andAsync
in JavaScript -
Use
callback
to Wait for a Function to Finish in JavaScript -
Use
promises
to Wait for a Function to Finish in JavaScript -
Use
async/await
to Wait for a Function to Finish Before Continuing Execution
This tutorial will introduce JavaScript Callbacks
, Promises
, and Async/await
and show you how to wait for an async function to finish before continuing the execution.
To understand what Promises
and Async/await
are, we first need to understand what the Sync
and Async
functions are in JavaScript.
Sync
and Async
in JavaScript
Synchronous programming executes one command at a time. When we call a function that performs a long-running action, it will stop the program until it finishes.
JavaScript is traditionally single-threaded, even with multi-cores. We can get it to run tasks only on a single thread called the main thread.
Such synchronous behavior is a limiting factor in the multi-threads but helps the user write codes without worrying about concurrency problems.
While in asynchronous programming, the long-running action will be executed in another thread other than the main thread, so the main execution is not blocked. When that long-running function finishes, the main program is informed and gets access to the results.
Most I/O primitives in JavaScript are non-blocking. Network requests, file systems operations are all non-blocking operations. Being blocked is the exception in JavaScript.
Since JavaScript is based on asynchronous programming techniques, there are multiple approaches such as callbacks
, promises
and async/await
enabling you to put your functions executions in sequence. So that a code-block or a function won’t be executed before another specific function finishes.
The above figure shows the clear variation between asynchronous and synchronous execution of two functions.
Use callback
to Wait for a Function to Finish in JavaScript
If we have synchronous statements, then executing those statements after each other is straight forward.
function one() {
console.log('I am function One');
}
function Two() {
console.log('I am function Two');
}
one();
Two();
Output:
I am function One
I am function Two
Suppose we want to execute two functions, functionOne()
and functionTwo()
such that functionOne()
should be executed after executing some asynchronus statements inside functionTwo()
.
function functionOne(_callback) {
// do some asynchronus work
_callback();
}
function functionTwo() {
// do some asynchronus work
functionOne(() => {
console.log('I am a callback');
});
}
functionTwo();
When executing the above code, the last thing printed in the console is I am a callback
. The famous callback
example is the setTimeout
function with a handler function to execute after timing out.
function testCallBack() {
console.log('log before use setTimeout function');
setTimeout(() => {
console.log('inside timeout');
}, 5000);
console.log('log after use setTimeout function');
}
testCallBack();
Output:
log before use setTimeout function
log after use setTimeout function
inside timeout
Use promises
to Wait for a Function to Finish in JavaScript
A promise
is an object representing the eventual fulfillment or failure of an asynchronous operation. We attach the fulfillment callback to the promise
with one or more then
statements, and when can call the error handler callback in the catch
.
doFirstThing()
.then(result => doSecondThing(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
console.log('The final result thing' + finalResult);
})
.catch(failureCallbackfunction);
}
To chain then
and catch
statements as the above example is one of the promises’ advantages. We promise to doSecondThing(result)
once the doFirstThing()
is fulfilled. The arguments to the then
are optional, but required if you have to return a result.
In case there is an error, the browser will look at the end of the chain for the catch
and execute it. It is very similar to the famous try-catch
.
The following example will help us understand the promises
chains and show us how we can wait for a function with asynchronous behavior to finish execution before we can continue execution.
var resolvedFlag = true;
let mypromise = function functionOne(testInput) {
console.log('Entered function');
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('Inside the promise');
if (resolvedFlag == true) {
resolve('Resolved');
} else {
reject('Rejected')
}
}, 2000);
});
};
mypromise()
.then((res) => {console.log(`The function recieved with value ${res}`)})
.catch((error) => {
console.log(`Handling error as we received ${error}`);
});
Output:
Entered function
Inside the promise
The function received with value Resolved
Creating a promise can be as easy as returning a new Promise()
. The Promise()
constructor receives a function as an argument, which should have two parameters - resolve
and reject
.
In case our event is fulfilled, and we need to return the result, we use the resolve()
function when succeeding in what we were doing. But if an error happens and needs to be handled, we use reject()
to send the error to the catch
.
We set the flag resolvedFlag = true
to simulate error handling in the catch
. If resolvedFlag
is set to be false
, the reject()
function is called, and the error is handled in the catch
block.
Output:
Entered function
Inside the promise
Handling error as we received Rejected
Use async/await
to Wait for a Function to Finish Before Continuing Execution
Another way to wait for a function to execute before continuing the execution in the asynchronous environment in JavaScript is to use async/wait
.
The async
function is the function that is declared by the async
keyword, while only the await
keyword is permitted inside the async
function and used to suspend the progress inside the async function until the promise-based asynchronous operation is fulfilled or rejected.
The async
and await
keywords enable asynchronous, promise-based behavior in a cleaner style.
Let’s understand how async/await
works. The function we are waiting for should return an instance of Promise class to wait for it to execute using the await keyword before calling it. As mentioned above, the function that contains the await
statement must be declared with the async
statement.
The following example shows how to wait for that promise-based function to finish before continuing the execution.
function testAsync() {
return new Promise((resolve, reject) => {
// here our function should be implemented
setTimeout(() => {
console.log('Hello from inside the testAsync function');
resolve();
;
}, 5000);
});
}
async function callerFun() {
console.log('Caller');
await testAsync();
console.log('After waiting');
}
callerFun();
Output:
Caller
Hello from inside the testAsync function
After waiting