Promises

What is a Promise?

Promises are JavaScript objects that represent the eventual result of an asynchronous operation.

Promises can be in one of three states: pending, resolved, or rejected.

  • Pending (the initial state): The operation has not completed yet.
  • Fulfilled: The operation has completed successfully and the promise now has a resolved value.
  • Rejected: The operation has failed and the promise has a reason for the failure.

While the value is not yet available, the Promise stays in the pending state. Afterwards, it transitions to one of the two states: resolved or rejected.

A promise is settled if it is either resolved or rejected.

Constructing a Promise Object

To create a new Promise object, we use the new keyword and the Promise constructor method:

const executorFunction = (resolve, reject) => {
  // executor
}

const myFirstPromise = new Promise(executorFunction);
  • When new Promise is created, the function (executor) runs automatically
  • resolve(value): if the job finished successfully, with result value.
  • reject(error): if an error occurred, error is the error object.
graph LR; A["new Promise (state: pending, result: undefined)"] A --> |"resolve"| B["state: fulfilled; result: value"] A -->|"reject"| C["state: rejected; result: error"]

setTimeout()

setTimeout() is a Node function which delays the execution of a callback function using the event-loop.

Example 1:

let callback = function() {
  console.log("It's been 3 seconds");
}
let timeToWait = 3000; //ms

global.setTimeout(callback, timeToWait);

// After 3 seconds, show "It's been 3 seconds"

This is a more common way to do the syntax:

// ES5
global.setTimeout(function() {
  console.log("It's been 3 seconds");
}, 3000);

// ES6
global.setTimeout(() => {
  console.log("It's been 3 seconds")
}, 3000);

Example 2:

let promise = new Promise(function(resolve, reject) {
  // the function is executed automatically when the promise is constructed

  // after 1 second, show the result is "done"
  setTimeout(() => resolve("done"), 1000);
});

then() and catch()

We use .then() with a success handler callback containing the logic for what should happen if a promise resolves.

We use .catch() with a failure handler callback containing the logic for what should happen if a promise rejects.

then syntax

promise.then(
  function(result) { /* handle a successful result */ },
  function(error) { /* handle an error */ }
);

For example

let promise = new Promise(function(resolve, reject) {
  setTimeout(() => resolve("done!"), 1000);
});

// resolve runs the first function in .then
promise.then(
  result => alert(result), // shows "done!" after 1 second
  error => alert(error) // doesn't run
);
  • The first argument of .then runs when the promise is resolved, and receives the result.
  • The second argument of .then runs when the promise is rejected, and receives the error.

catch

.catch handles the error object

const promise = new Promise((resolve, reject) => {  
  setTimeout(() => {
    reject(Error('Promise Rejected Unconditionally.'));
  }, 1000);
});

promise.then((res) => {
  console.log(value);
});

promise.catch((err) => {
  alert(err);
});

Chaining Multiple Promises

if we have a sequence of asynchronous tasks, we can use promises chaining

We do this by chaining multiple .then() and .catch().

new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000); 

}).then(function(result) { 

  alert(result); // 1
  return result * 2;

}).then(function(result) { 
  alert(result); // 2
  return result * 2;

}).then(function(result) {

  alert(result); // 4
  return result * 2;

});

Promise.all()

Promise.all() method can be used to execute multiple promises in parallel.

The syntax:

let promise = Promise.all([...promises...]);

Promise.all takes an array of promises and returns a new promise.

Promise.all([
  new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
]).then(alert); // 1,2,3 when promises are ready

If any of the promises is rejected, the promise returned by Promise.all immediately rejects with that error.