ways to make code asynchronous

In javascript making the code asynchronous is done using promises, async/await and using the methods explicitly made which support asynchronous behaviour.

Promises: Promises provide a cleaner way to handle asynchronous operations and their results compared to callbacks. They represent a value that may be available now, or in the future, or never. Promises can be chained together, making it easier to compose asynchronous operations sequentially.


function fetchData() {

  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = { id: 1, name: 'John' };
      if(data){
        resolve(data);
      }else{
        const error = new Error('Failed to fetch data');
        reject(error);
      }    
    }, 2000); 
  });
}

// Using the fetchData function with a promise
fetchData()
  .then((data) => {
    // This code block executes when the promise is resolved
    console.log('Data fetched successfully:', data);
  })
  .catch((error) => {
    // This code block executes if there's an error or the promise is rejected
    console.error('Error fetching data:', error.message);
  });

console.log('Fetching data...'); // This line executes immediately

Here when we call fetchData(), it returns us a promise which is executing asynchronously. soon as the code gets into resolve or reject, result is presented to us. We can get the result using chaining the 'then' and 'catch'. If the result comes throught resolve, we can get it on 'then' otherwise we need to catch the error using 'error' . Also even if you don't write any blocking code or heavy i/o code which could take large amount of time, it will still run as async operation.

Async/Await: Async functions and the await keyword provide syntactic sugar over promises, making asynchronous code look more like synchronous code. Async functions return promises implicitly, and the await keyword pauses execution until the promise is resolved, allowing for sequential asynchronous code without nested callbacks.

function fetchData() {

  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = { id: 1, name: 'John' };
      resolve(data);
    }, 2000); 
  });
}


async function fetchDataAsync() {
  try {
    // Use the await keyword to wait for the promise to resolve
    const data = await fetchData();
    console.log('Data fetched successfully:', data);
  } catch (error) {
    // Handle errors if the promise is rejected
    console.error('Error fetching data:', error.message);
  }
}

// Call the async function
console.log('Fetching data...');
fetchDataAsync();

Here in this example we are using async keyword to make fetchDataAsync() function to run as asynchronously. Again it doesn't matter if it has any blocking code or not it will run asynchronously.

The third type includes the usage of async methods which are inbuilt in js or using packages or libraries which support async operations. such as setTimeOut, setInterval, various methods of fs module.

const fs = require('fs');

fs.readFile('index.js','utf8', (err, data)=>{
    // code
})

this method by fs module behaves as async method. But if we use fs.readFileSync then this method will run synchronously.

I hope this article helped you to better understand how to make javascript code run asynchronously.