Vinay Kumar

ES6 Promise to the rescue

When people using the Javascript language started loosing their sanity facing callback hell, EcmaScript(original name of JavaScript) decided to incorporate promise.

The job of promise is to either complete or fail a asynchronous task. The promise class constructor accepts two arguments resolve and reject. Upon successful completion of any task resolve() can be made use of and if there is a need to throw an error reject() is used.

const success = new Promise((resolve, reject) => {
  return resolve('Hurray! Everything went well');
});

const failure = new Promise((resolve, reject) => {
  return reject(new Error('something went wrong.'));
});

Now to check whether the promise has been fulfilled or rejected after execution, the Promise class provides with then() and catch() methods.

success.then(message => console.log(message)).catch(error => console.log(`Oops! ${error.message}`));
// Output: Hurray! Everything went well

failure.then(message => console.log(message)).catch(error => console.log(`Oops! ${error.message}`));
// Output: Oops! something went wrong.
The then() and catch() functions can be used more than once thanks to method chaining. Both the function returns a promise.

const success = (message) => new Promise((resolve, reject) => {
  return resolve(message);
});

const failure = (message) => new Promise((resolve, reject) => {
  return reject(new Error(message));
});

/**
* Output:
* first success
* second success
*/
success('first success')
  .then((response) => { console.log(response); return success('second success'); })
  .then((response) => { console.log(response); })
  .catch((response) => { console.log(response);});


/**
* Output:
* first success
* first failure
*/
success('first success')
  .then((response) => { console.log(response); return failure('first failure'); })
  .then((response) => { console.log(response); })
  .catch((error) => { console.log(error.message);});

/**
* Output:
* first success
* first failure
* I decide to continue
*/
success('first success')
  .then((response) => { console.log(response); return failure('first failure'); })
  .catch((error) => { console.log(error.message); return success('I decide to continue');})
  .then((response) => { console.log(response); });

At times there may be situation where certain lines of code ought to be executed irrespective of promise fulfillment or failure. To the rescue is finally() method.

/**
* Output:
* first success
* first failure
* I am guaranteed to execute no matter the state.
*/
success('first success')
  .then((response) => { console.log(response); return failure('first failure'); })
  .catch(error => console.log(error.message))
  .finally(() => { console.log('I am guaranteed to execute no matter the state.'); });

So what is the big deal with Promise? Well it is possible to achieve synchronous like nature with much code clarity

The execution of the code in the examples provided till now will be in series. It is possible to run the code in parallel whenever need arises using Promise.all(). The method accepts an iterable containing multiple promise. If any one of the promise contained in iterable throws an error, then it rejects immediately.

/**
* Output:
* ['first success', 'second success'] //Note: returned value is array
*/
Promise.all([success('first success'), success('second success')])
  .then((response) => { console.log(response); })
  .catch((error) => { console.log(error.message);});

/**
* Output:
* first failure
*/
Promise.all([success('first success'), success('second success'), failure('first failure')])
  .then((response) => { console.log(response); })
  .catch((error) => { console.log(error.message);});

To sum up: Using promise will save you from entering the hell of callbacks.