Asynchronous programming in Node.js

Search for a command to run...

No comments yet. Be the first to comment.
Automating the boring stuff in job applications, while keeping the final decision in your hands.

Automating the boring stuffs ...

Managing S3 Case Sensitivity in Python Workflows

π©οΈ Cloud computing has revolutionized how applications are developed and deployed, providing a more flexible and scalable environment for running workloads. AWS offers several services for event-driven computing, including Amazon CloudWatch Events a...

Introductionπ Looking to streamline your complex workflows and keep everything on track? Look no further than state machines - a powerful tool for precision and ease in process management. πͺπΌ And when it comes to implementing state machines, AWS S...

Peterson Oaikhenah -- Senior Software Engineer | Community leader | Cloud Engineer | Open Source
38 posts
Motivated senior software engineer, open-source advocate & community leader π»β‘οΈ. Sharing valuable insights to help others scale π‘. Building strong communities π. Passionate about promoting tech
Asynchronous I/O is a form of input/output processing that permits other processing to continue before the transmission has finished.
Asynchronous programming in JavaScript can only be achieved with functions being first-class citizens of the language. Thus functions can be passed around like any other variable to other functions.
Functions that can take other functions as arguments are called higher-order functions.
In Javascript, one efficient way of handling asynchronous or expensive operations is using promises. This is because in an asynchronous operation there is no guarantee of exactly when the operation will complete and the result it will return. A promise object thus helps us to cater for the intermediate state of the operation, whether it is successful(resolve), pending(ongoing), or fails(reject).
Promise.resolve() //success
Promise.reject() // fail
We established above that a Promise object represents the result of an asynchronous function. Promises can be used to avoid chaining of callbacks, referred to as the Callback hell.
It's easier to work with promises when working on async operations, but unfortunately, Nodejs has many of its APIs written with callbacks. (Promises were updates to the ECMAScript)
Here's an example using the file stream API. fs.readFile
const fs = require('fs')
fs.readFile(filePath, options, callback)
Here, the callback function contains at least two arguments. The first argument must be an error object and the data returned.
fs.readFile('file-path', (err, data) => {
if (err) {
//throw new error
}
//do something with data return
})
Below we convert a callback styled Node API to a promise, using the util.promisify API
const util = require('util');
const fs = require('fs');
const readFilePromise = util.promisify(fs.readFile)
readFilePromise('file-path').then((data) => {
//do something with data return
}).catch((error) => {
//throw new error
});
We can also use the async/await operation to resolve a promise.
const readFilePromise = util.promisify(fs.readFile)
async function(){
const data = await readFilePromise;
console.log(data);
}
In javascript, we can create asynchronous functions that return a promise π . see the example below.
const myPromise = new Promise((resolve, reject) = {
setTimeout(() =>
{
console.log('resolving the promise ...');
resolve('resolved!');
}, 5000); // usually would be an asychronous operation
reject('rejected!');
});
console.log(myPromise);
We can chain the Promises using .then() and .catch() higher-order functions.
The .then() accepts a callback as an argument and invokes the resolved Promise. The .catch() accepts a callback and is executed when the Promise is rejected.
see the example below.
const resolvedCallback = (data) => console.log(data);
const rejectedCallback = (err) => console.log(err);
myPromise.then(resolvedCallback).catch(rejectedCallback);
Unlike the examples we wrote above, we can return the state of a promise object without conditions. this might be useful when we need to resolve or reject multiple independent asynchronous operations. it's as simple as writing;
Promise.resolve();
Promise.reject();
We notice in the Node environment, the Promise object is globally available, interesting right! π
When dealing multiple independent promises, the methods Promise.all() and Promise.race() can be useful. Both methods accept an array of promises as an argument.
While using Promise. all(), the .then method is only invoked after the last promise is resolved.
const promiseArr = [
Promise.resolve("data1")
Promise.resolve("data2")
Promise.resolve("data3")
]
Promise.all(promiseArr).then(results =>
console.log(results)
)
// [ data1, data2, data3 ]
While using Promise.race(), the .then method is invoked only when the first promise is resolved.
Promise.race(promiseArr).then(results =>
console.log(results)
)
// data1
One thing to note as well is that the least expensive function will always resolve first. This enables us to run multiple asynchronous operations and act upon the one that finishes first.
Thanks for the audience and I hope you found this article helpful getting started with promises in Javascript π€. Feel free to reach out to me on Github, Twitter and LinkedIn. Do drop a like, comment, and share π.
Find out more about Graceful asynchronous programming with Promises