Using Async Await In Node.js

Using Async Await In Node.js

Using Async Await In Node.js

Emmanuel Ighosewe
Author
Emmanuel Ighosewe

The term asynchronous is used where two or more events do not occur simultaneously. Simply put, several related things can occur without waiting for the completion of the previous action.

Due to the single-threaded nature of JavaScript, asynchronous functions are highly essential in JavaScript. Asynchronous functions allow the JavaScript event loop to do other things when the function requests another resource.

For example, you can use synchronization codes in the API when you access a database and return data from it, when you access a video stream from a webcam, or when you use the screen of a VR headset; these codes will pull files from the network.

What are Async functions?

Asynchronous functions are available in Node and are designated using the async keyword when declaring them. Though you do not write them to return a promise, they will always do. In addition, the await keyword is available only in async functions and cannot be used in a wide range.

In an asynchronous application, you can either use await for any promises or catch the rejection cause. So if you apply logic using Promise:

function handler (req, res) {

return request('https://user-handler-service')

.catch((err) => {

logger.error('Http error', err);

error.logged = true;

throw err;

})

.then((response) => Mongo.findOne({ user: response.body.user }))

.catch((err) => {

!error.logged && logger.error('Mongo error', err);

error.logged = true;

throw err;

})

.then((document) => executeLogic(req, res, document))

.catch((err) => {

!error.logged && console.error(err);

res.status(500).send();

});

}

It can look like asynchronous code with the keyword async/await:

async function handler (req, res) {

let response;

try {

response = await request('https://user-handler-service');

} catch (err) {

logger.error('Http error', err);

return res.status(500).send();

}

let document;

try {

document = await Mongo.findOne({ user: response.body.user });

} catch (err) {

logger.error('Mongo error', err);

return res.status(500).send();

}

executeLogic(document, req, res);

}

Callbacks in JavaScript

Callbacks were the original way of dealing with the asynchronous nature of JavaScript engines. Callbacks are functions essentially performed when synchronous ends or at I/O blocking operations.

Example of a Callback:

app.get('/', function(){

function1(arg1, function(){

...

})

});

However, there is an issue when using this type of code. It can result in problems, and the code will become disorganized when the functions are too much. When this happens, then we have what we call callback hell.

Example of Callback Hell:

function translateLetter(letter, callback) {

return setTimeout(2000, () => {

callback(letter.split("").reverse().join(""));

});

}

function assembleToy(instruction, callback) {

return setTimeout(3000, () => {

const toy = instruction.split("").reverse().join("");

if (toy.includes("wooden")) {

return callback(`polished ${toy}`);

} else if (toy.includes("stuffed")) {

return callback(`colorful ${toy}`);

} else if (toy.includes("robotic")) {

return callback(`flying ${toy}`);

}

callback(toy);

});

}

function wrapPresent(toy, callback) {

return setTimeout(1000, () => {

callback(`wrapped ${toy}`);

});

}

How Promises Work in JavaScript

The promise object in JavaScript is a representation of an asynchronous operation and its ultimate value that will be completed or eventually fail.

You can find a promise in one of the states below:

Pending: This indicates the initial stage, not yet fulfilled or rejected.

Fulfilled: This is an indication that the operation was completed

Rejected: The operation eventually fail.

The executor is a function that was passed to a new promise. It has arguments (resolve and reject) that are known as callbacks and are provided by JavaScript. It does not matter when the executor finally gets results; it must call one of the callbacks.

Following is an example of a promise:

const myPromise = new Promise(function(resolve, reject) => {

setTimeout(() => {

resolve('foo');

}, 300);

});

Below are examples of a fulfilled and a rejected promise:

// fulfilled promise

let promise = new Promise(function(resolve, reject) {

setTimeout(() => resolve(new Error("done!")), 1000);

});

// resolve runs the first function in .then

promise.then(

result => alert(result), // shows "done!" after 1 second

error => alert(error) // doesn't run

);

// rejected promise

let promise =

new Promise(function(resolve, reject) {

setTimeout(() => reject(new Error("Whoops!")), 1000);

});

// reject runs the second function in .then

promise.then(

result => alert(result), // doesn't run

error => alert(error) // shows "Error: Whoops!" after 1 second

);

How to Use Async/Await with Error Handling

We can handle errors using a try-catch block like this:

const loadData = async () => {

try{

const url = "https://jsonplaceholder.typicode.com/todos/1";

const res = await fetch(url);

const data = await res.json();

console.log(data);

} catch(err) {

console.log(err)

}

};

loadData();

The above will take care of errors while getting data like wrong syntax, wrong domain names, network errors, and many more.

If you want to handle an API response code error message, you can utilize res.ok (res is the variable that will store the response). A true Boolean value returns if the response code is between 200 and 209.

const loadData = async () => {

try{

const url = "https://jsonplaceholder.typicode.com/todos/qwe1";

const res = await fetch(url);

if(res.ok){

const data = await res.json();

console.log(data);

} else {

console.log(res.status); // 404

}

} catch(err) {

console.log(err)

}

};

loadData();

OUTPUT:

// 404

How an Async Function Returns a Promise

This is one of the characteristics of asynchronous functions, it is sure that their return value will be translated into promises. To process the data returned by the asynchronous function, we can use the keyword to retrieve the data.

const loadData = async () => {

try{

const url = "https://jsonplaceholder.typicode.com/todos/1";

const res = await fetch(url);

const data = await res.json();

return data

} catch(err) {

console.log(err)

}

};

const data = loadData().then(data => console.log(data));




Drop us a line and let’s get in touch - embrace remote working through Upstack!