/

How to Use Promises and Await with Node.js Callback-Based Functions

How to Use Promises and Await with Node.js Callback-Based Functions

In the world of Node.js, many APIs and libraries were built before the introduction of promises. As a result, they rely on a callback-based solution. However, working with nested callbacks can lead to a complex and messy code structure commonly known as “callback hell.” Thankfully, there is a solution: the use of promises and the await keyword.

To remove callbacks and make use of promises, Node.js provides a useful utility called promisify from the util module. By utilizing promisify, you can convert callback-based functions into functions that support promises and enable the use of the async/await syntax.

To use promisify, import it from the util module:

1
const { promisify } = require('util');

Then, create new functions using promisify:

1
2
3
const ahget = promisify(client.hget).bind(client);
const asmembers = promisify(client.smembers).bind(client);
const ahkeys = promisify(client.hkeys).bind(client);

By adding the letter “a” as a prefix to the function name, it indicates that the function is now asynchronous.

With these promisified functions, you can transform a callback-based “callback hell” scenario into a cleaner and more readable code structure by using the async/await syntax:

1
2
3
4
5
6
7
const currentUserName = await ahget(`user:${req.session.userid}`, 'username');
const followers = await asmembers(`followers:${currentUserName}`);
const users = await ahkeys('users');

res.render('dashboard', {
users: users.filter((user) => user !== currentUserName && followers.indexOf(user) === -1)
});

This approach is particularly useful when working with third-party libraries where you don’t have direct access to modify the original callback-based functions.

Under the hood, the promisify function wraps the original function in a promise, allowing you to use await to handle the asynchronous behavior.

Alternatively, you can manually create a promise and return it from a function, allowing you to use async/await syntax:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const handleLogin = (req, user) => {
return new Promise((resolve, reject) => {
req.login(user, (err) => {
if (err) {
return reject({
error: true,
message: err,
});
}
return resolve({
success: true,
});
});
});
}

// ...
const resultLogin = await handleLogin(req, user);

By using promises and await, you can simplify the handling of callback-based functions and create more readable and maintainable code.

tags: [“Node.js”, “promises”, “async/await”, “callback-based functions”, “callback hell”, “promisify”]