Learn

Developers sometimes classify outlier functions used to maintain code and debug certain aspects of a program’s functionality as utility functions. Utility functions don’t necessarily create new functionality in a program, but you can think of them as internal tools used to maintain and debug your code. The Node.js util core module contains methods specifically designed for these purposes. The util module can be required into the file using:

const util = require('util');

Once required, you have access to many useful objects and methods within the util module. One important object is types, which provides methods for runtime type checking in Node.

const util = require('util'); const today = new Date(); const earthDay = 'April 22, 2022'; console.log(util.types.isDate(today)); console.log(util.types.isDate(earthDay));

In the above example, we first require in the util module. Next, we declare two variables: today stores today’s date as an instance of the Date object, and earthDay stores the date of Earth Day as a string. We then log the results of type checking each variable using util.types.isDate(). The types.isDate() method checks for Date objects and returns a boolean value, giving us:

true false

Since today is a Date object, it returns true, and since earthDay is a string, it returns false!

Another important util method is .promisify(), which turns callback functions into promises. As you know, asynchronous programming is essential to Node.js. In the beginning, this asynchrony was achieved using error-first callback functions, which are still very prevalent in the Node ecosystem today. But since promises are often preferred over callbacks and especially nested callbacks, Node offers a way to turn these into promises. Let’s take a look:

function getUser (id, callback) { return setTimeout(() => { if (id === 5) { callback(null, { nickname: 'Teddy' }) } else { callback(new Error('User not found')) } }, 1000) } function callback (error, user) { if (error) { console.error(error.message) process.exit(1) } console.log(`User found! Their nickname is: ${user.nickname}`) } getUser(1, callback) // -> `User not found` getUser(5, callback) // -> `User found! Their nickname is: Teddy`

Here we have a function that queries a database for a specified user ID. getUser methods are very common in back-end applications, and most will also support error-first callbacks. Since a database query typically takes longer to run than other operations, we simulate the query with a setTimeout() method that executes a callback function after 1000 milliseconds (or 1 second). If the user with the specified ID is found, the callback function is executed with null passed in as the argument for the error parameter, and an object containing the returned user information is passed in as an argument for the user parameter. If the user is not found, the callback function is executed, passing in a new Error as the argument for the error parameter. A second argument for user is not necessary since the function will end in the case of an error.

This way of handling this function may seem a bit convoluted these days, but with .promisify(), we can easily change it into a modern, cleaner, and more maintainable version of itself:

const getUserPromise = util.promisify(getUser); getUserPromise(id) .then((user) => { console.log(`User found! Their nickname is: ${user.nickname}`); }) .catch((error) => { console.log('User not found', error); }); getUser(1) // -> `User not found` getUser(5) // -> `User found! Their nickname is: Teddy`

We declare a getUserPromise variable that stores the getUser method turned into a promise using the .promisify() method. With that in place, we’re able to use getUserPromise with .then() and .catch() methods (or we could also use the async...await syntax here) to resolve the promise returned or catch any errors.

Now, this is an extremely simplified example, but it’s helpful to recognize how to use this important tool when you start working with more complex callback functions.

Instructions

1.

In app.js we’ve required in an object containing long distance hiking trails in the US. You can view that object by opening the trails.js file from the navigator.

Below that is a callback function, getTrailDistance, that’s ready to be converted using util.promisify().

Start by requiring the util module at the top of the app.js, and saving it to a util variable.

2.

Next, below the callback function call at the bottom of the file, using const, declare a variable, getTrailDistancePromise, and store util.promisify(getTrailDistance).

3.

Then, call the new promisified function, getTrailDistancePromise, with 'North Country' (or any trail property from the trails object in trails.js) as the only argument. Resolve the promise with a .then() method, and reject the promise with a .catch() method.

4.

Lastly, inside of then(), log to the console:

`The ${nickname} is ${mi} miles long!`

where nickname is the nickname and mi is the distance of the passed-in trail. Inside catch(), pass in a function that logs any errors.

Way to go! You just turned a dusty old callback function into a shiny new promise! You should see identical responses from the callback and the promise.

Take this course for free

By signing up for Codecademy, you agree to Codecademy's Terms of Service & Privacy Policy.
Already have an account?