Javascript Promise

·

4 min read

JavaScript promises are a powerful tool for writing asynchronous code. They provide a way to handle asynchronous results in a synchronous-like manner, making it easier to reason about and work with asynchronous code.

Promises are objects that represent the eventual result of an asynchronous operation. They have a then method, which allows you to specify a callback to be executed when the asynchronous operation completes, as well as a catch method, which allows you to specify a callback to be executed if the asynchronous operation fails.

Here's an example of how you might use a promise to load some data from a server:

function loadData() {
    return new Promise((resolve, reject) => {
      // make an HTTP request to load the data
      const xhr = new XMLHttpRequest();
      xhr.open('GET', '/data');
      xhr.onload = () => {
        if (xhr.status === 200) {
          // if the HTTP request is successful, resolve the promise with the response data
          resolve(xhr.response);
        } else {
          // if the HTTP request is not successful, reject the promise with an error message
          reject(new Error(`Unable to load data: ${xhr.statusText}`));
        }
      };
      xhr.onerror = () => {
        // if there is a network error, reject the promise with an error message
        reject(new Error('Network error'));
      };
      xhr.send();
    });
  }
  // use the promise
  loadData()
    .then(data => {
      // do something with the data
      console.log(data);
    })
    .catch(error => {
      // handle any errors
      console.error(error.message);
    });

Promises also have a finally method, which allows you to specify a callback to be executed whether the promise is resolved or rejected. This is useful for cleaning up resources or performing other tasks that should be done regardless of the outcome of the asynchronous operation.

Promises can also be composed using methods such as Promise.all and Promise.race. Promise.all allows you to wait for an array of promises to all be resolved, while Promise.race allows you to specify a callback to be executed as soon as one of the promises in an array is resolved or rejected.

Chaining promises

One of the most powerful features of promises is the ability to chain them together. This allows you to build up a sequence of asynchronous operations, with each operation being executed only after the previous one has completed.

Here's an example of chaining promises:

loadData()
  .then(data => {
    // do something with the data
    return transformData(data);
  })
  .then(transformedData => {
    // do something with the transformed data
    return storeData(transformedData);
  })
  .then(() => {
    console.log('All operations completed successfully');
  })
  .catch(error => {
    // handle any errors
    console.error(error.message);
  });

In this example, the transformData and storeData functions both return promises, and the then method is used to specify a callback to be executed when each promise is resolved. If any of the promises are rejected, the error will be caught by the catch method at the end of the chain.

Handling multiple asynchronous operations concurrently

In some cases, you may want to perform multiple asynchronous operations concurrently, rather than waiting for each one to complete in sequence. You can use the Promise.all method to do this.

Here's an example of using Promise.all:

Promise.all([loadData(), loadMoreData()])
  .then(([data, moreData]) => {
    // do something with the data and moreData
  })
  .catch(error => {
    // handle any errors
    console.error(error.message);
  });

In this example, the loadData and loadMoreData functions both return promises, and Promise.all is used to wait for both of them to be resolved. If either of the promises are rejected, the error will be caught by the catch method.

Using async/await

JavaScript also has a new way of writing asynchronous code called async/await. This syntax allows you to write asynchronous code in a synchronous-like style, using the async keyword to define an asynchronous function and the await keyword to wait for a promise to be resolved.

Here's an example of using async/await with promises:

async function loadAndTransformData() {
  try {
    const data = await loadData();
    const transformedData = await transformData(data);
    return transformedData;
  } catch (error) {
    // handle any errors
    console.error(error.message);
  }
}

loadAndTransformData().then(transformedData => {
  // do something with the transformed data
});

In this example, the loadAndTransformData function is marked as async, which means it returns a promise. The await keyword is used to wait for the loadData and transformData promises to be resolved. If either of these promises is rejected, the error will be caught by the catch block.