A simple beginner’s guide to Node.Js and Npm (Part 2)

Varad Shevade
3 min readAug 7, 2020

Basics of writing Asynchronous Codes in Node.js

Here we will see the 3 most common ways to handle asynchronous methods.

  • Through Callbacks: One of the most primitive and still widely used approaches.

Example: Following is a simple example to print current time every 1000 milliseconds.

function cb() {
console.log(new Date().toLocaleTimeString());
}
setInterval(cb, 1000);

Callbacks are nothing but functions, which are passed as arguments to another function. One of the important principles of functional programming, they are invoked inside the function when the data is available to be returned. Here it doesn’t matter if the data is going to be available immediately, or after a certain time. Thus making callbacks one of the most popular techniques to handle asynchronous situations.

  • Through Promises: The most decent and recommended method.

Example:

var promise = new Promise((resolve, reject) => {
setTimeout(()=>{
var time = new Date().toLocaleTimeString();
if(time) {
resolve(time);
} else {
reject(new Error("date error!"))
}
}, 3000);
});
promise.then(data=>{
console.log(data)
}).catch(err => {
console.error(err)
})

In Node.js promises are objects of the “Promise” class. Promises are unknown at the time of their creation but act as a placeholder for a future value to be returned. Even if there is success or failure, promises make sure that there is at least a value to be returned.

Inside a promise the “reject” & “resolve” are actually callbacks, which should be invoked based on the integrity of the data. Promise object provides methods like then() & catch() for chaining, which ease the burden of explicitly handling error and success scenarios. One of the most important advantages of promises over callbacks is its ability to efficiently handle “array of asynchronous definitions” through Promise.all().

Detailed info on promises at:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

  • Through async/await: A more cleaner approach with limited coding. Works with promises, and totally eliminates the need of then() & catch() methods. It is very simple and easy to use.

Example: Consider the same example as above, but in case of then(), catch() we use await. Always use it inside a function marked as async.

async function timeout() {
var current = await promise;
console.log(current);
}

Here the entire timeout function now will be treated as an asynchronous code snippet. The await inside async will make the code execution wait at that line, until the associated promise is resolved/rejected. The only drawback here is that error scenarios need to be handled explicitly in a try-catch block. async/await gives more of a synchronous kind of representation for an asynchronous code.

Importing and Exporting external modules.

  • require(): It is built-in and can be used to include JavaScript functions/modules from different files. Whenever require() is used for a file, it will read and execute that file, and return its “exports” object.

Example:

demo1.js looks something like this.

exports.message = “This is demo 1.”;

Now suppose I have another file called main.js. Now to include demo1 inside main.js, use require() method.

main.js

var demo1 = require("./demo1.js");
console.log(demo1.message); //outputs: "This is demo 1."

Native support for es modules from version >8.5.0 is made available, hence instead of using require(), we can make use of the “import” keyword to do the same.

Eg.:

import * as demo1 from "./demo1.js"; //here "*" used to import all objects
console.log(demo1.message); //outputs: "This is demo 1."
  • exports & module.exports: Both of these can be used to export any properties of the object. Initially both point to the same empty object.

module.exports => {} <= exports

So Eg.:

module.exports.foo = “FOO”;exports.bar = “BAR”;

Final exported object will be as follows:

{“foo”: “FOO”, “bar”, “BAR”}

In case you have to export a function, use module.exports.

The reason being, whenever the actual export takes place, the data associated with module.exports is exported. And if we assign a function to the exports variable, then the exports & module.exports will no longer be pointing to the same object, and hence that function will never be exported.

So it is best to export your functions and values as follows.

module.exports = {
message: "This is demo 1.",
display: fn()
}

Don’t forget to checkout part 3 of the tutorial at:

--

--