What is promise, promise.all and promise.race? How do you chain promises?

A promise is an object that may produce a single value some time in the future: either a resolved value, or a reason that it’s not resolved (e.g., a network error occurred).
A promise is an object which can be returned synchronously from an asynchronous function. It will be in one of 3 possible states:
  • Fulfilled: onFulfilled() will be called (e.g., resolve() was called)
  • Rejected: onRejected() will be called (e.g., reject() was called)
  • Pending: not yet fulfilled or rejected
A promise is settled if it’s not pending (it has been resolved or rejected). Sometimes people use resolved and settled to mean the same thing: not pending.
Once settled, a promise can not be resettled. Calling resolve() or reject() again will have no effect. The immutability of a settled promise is an important feature.
Promises following the spec must follow a specific set of rules:
  • A promise or “thenable” is an object that supplies a standard-compliant .then() method.
  • A pending promise may transition into a fulfilled or rejected state.
  • A fulfilled or rejected promise is settled, and must not transition into any other state.
  • Once a promise is settled, it must have a value (which may be undefined). That value must not change.

Creating a promise

The Promise API exposes a Promise constructor, which you initialize using new Promise():


const fs = require('fs')


const getFile = (fileName) => {

  return new Promise((resolve, reject) => {

    fs.readFile(fileName, (err, data) => {

      if (err) {

        reject (err)  // calling `reject` will cause the promise to fail with or without the error passed as an argument

        return        // and we don't want to go any further

      }

      resolve(data)

    })

  })

}


getFile('/etc/passwd')

.then(data => console.log(data))

.catch(err => console.error(err))


Chaining promises

A promise can be returned to another promise, creating a chain of promises.


A great example of chaining promises is the Fetch API, which we can use to get a resource and queue a chain of promises to execute when the resource is fetched.


The Fetch API is a promise-based mechanism, and calling fetch() is equivalent to defining our own promise using new Promise().


Example:


const status = response => {

  if (response.status >= 200 && response.status < 300) {

    return Promise.resolve(response)

  }

  return Promise.reject(new Error(response.statusText))

}


const json = response => response.json()


fetch('/todos.json')

  .then(status)    // note that the `status` function is actually **called** here, and that it **returns a promise***

  .then(json)      // likewise, the only difference here is that the `json` function here returns a promise that resolves with `data`

  .then(data => {  // ... which is why `data` shows up here as the first parameter to the anonymous function

    console.log('Request succeeded with JSON response', data)

  })

  .catch(error => {

    console.log('Request failed', error)

  })


Orchestrating promises

Promise.all()

If you need to synchronize different promises, Promise.all() helps you define a list of promises, and execute something when they are all resolved.


Example:


const f1 = fetch('/something.json')

const f2 = fetch('/something2.json')


Promise.all([f1, f2])

  .then(res => {

    console.log('Array of results', res)

  })

  .catch(err => {

    console.error(err)

  })

The ES2015 destructuring assignment syntax allows you to also do


Promise.all([f1, f2]).then(([res1, res2]) => {

  console.log('Results', res1, res2)

})

You are not limited to using fetch of course, any promise can be used in this fashion.


Promise.race()

Promise.race() runs when the first of the promises you pass to it resolves, and it runs the attached callback just once, with the result of the first promise resolved.


Example:


const first = new Promise((resolve, reject) => {

  setTimeout(resolve, 500, 'first')

})

const second = new Promise((resolve, reject) => {

  setTimeout(resolve, 100, 'second')

})


Promise.race([first, second]).then(result => {

  console.log(result) // second

})

Comments

Popular posts from this blog

What test framework did you use to test your nodejs applications

What is V8 Engine? What is the relationship between Node.js and V8?