JavaScript Promises: 9 Questions

Learn about promises & take the quiz!

published 5 days agoNov 26th, 2019

updated 1 day agoNov 30th, 2019

Do you know your JavaScript & Promises???

  • Prove your JavaScript skillz! 🚀
  • No login or signup required. ✨
  • Multiple choice. 🤖 … How difficult can it be, eh?

Goal

My goal is to try a new ‘quiz tool’ I built for my blog, and get feedback on how well you learned from the excercise.

If you get stuck

  1. Read the Hints (Green button, lower left corner). Some include a few animated answers w/ detailed annotations, while others offer only a few clues. I can’t give away all the answers so easy!
    Seriously though, this is intentional, the answers are there. Skip ahead or try the code snippets out, then change it, and play some more.
  2. Try the code in your browser’s Console (try shortcut F12 or search it) or use repl.it*.
  3. Please feel free to Tweet at me @justsml. I’d love to hear your thoughts!

Loading...
A few more seconds...

Multiple .catch’s

var p = new Promise((resolve, reject) => {
  reject(Error('The Fails!'))
})
p.catch(error => console.log(error.message))
p.catch(error => console.log(error.message))

What will the output be?

  • print message once
  • print message twice
  • UnhandledPromiseRejectionWarning
  • process exits

We create a Promise using the constructor method, triggering an error immediately with the reject callback.

Then the .catch handlers work like the DOM’s .addEventListener(event, callback) or Event Emitter’s .on(event, callback) where multiple handler callbacks can be added. Each will be called with the same arguments.

Multiple .catch’s

var p = new Promise((resolve, reject) => {
  return Promise.reject(Error('The Fails!'))
})
p.catch(error => console.log(error.message))
p.catch(error => console.log(error.message))

What will the output be?

  • print message once
  • print message twice
  • UnhandledPromiseRejectionWarning
  • process exits

annotated-code/question-2.png

When using the Promise constructor you must invoke either resolve() or reject() callbacks. The Promise constructor doesn’t use your return value, so the additional Promise created with Promise.reject() will effectively never be heard from again.

With no .catch following the Promise.reject(), the answer is UnhandledPromiseRejectionWarning.

Chaining .then and .catch’s

var p = new Promise((resolve, reject) => {
    reject(Error('The Fails!'))
  })
  .catch(error => console.log(error))
  .then(error => console.log(error))

What will the output be?

  • print error and `undefined`
  • print error twice
  • UnhandledPromiseRejectionWarning
  • undefined

annotated-code/question-3.png

When chaining .then’s and .catch’s it is helpful to think of them as a series of steps. Each .then receives the value returned by the previous .then (as its argument.) However, if your “step” encountered an error, any subsequent .then “steps” will be skipped until a .catch is encountered. If you want to override an error, all you need to do is return a non-error value. It can be accessed via any subsequent .then.

Hint: console.log() always return undefined.

Chaining .catch’s

var p = new Promise((resolve, reject) => {
    reject(Error('The Fails!'))
  })
  .catch(error => console.log(error.message))
  .catch(error => console.log(error.message))

What will the output be?

  • print error message once
  • print error message twice
  • UnhandledPromiseRejectionWarning
  • process exits

When chaining .catch’s, each one only handles errors thrown in previous .then or .catch “steps”. In this example the first .catch returns the console.log which could only be accessed via adding a .then() after both the .catch’s.

Multiple .catch’s

new Promise((resolve, reject) => {
    resolve('Success!')
  })
  .then(() => {
    throw Error('Oh noes!')
  })
  .catch(error => {
    return "actually, that worked"
  })
  .catch(error => console.log(error.message))

What will the output be?

  • print message once
  • print message twice
  • UnhandledPromiseRejectionWarning
  • nothing prints

Hint: .catch’s can be used to ignore (or override) errors simply by returning a regular value.

This trick works only when there is a subsequent .then to receive the value.

Flow between .then’s

Promise.resolve('Success!')
  .then(data => {
    return data.toUpperCase()
  })
  .then(data => {
    console.log(data)
  })

What will the output be?

  • print "Success!" and "SUCCESS!"
  • print "Success!"
  • print "SUCCESS!"
  • nothing prints

Hint: .then’s pass data sequentially, from return value to the next .then(value => /* handle value */).

A return is key in order to pass a value to the next .then.

Flow between .then’s

Promise.resolve('Success!')
  .then(data => {
    return data.toUpperCase()
  })
  .then(data => {
    console.log(data)
    return data
  })
  .then(console.log)

What will the output be?

  • print "SUCCESS!"
  • print "Success!"
  • print "SUCCESS!" and "SUCCESS!"
  • nothing prints

There are 2 console.log calls which will be called.

Flow between .then’s

Promise.resolve('Success!')
  .then(data => {
    data.toUpperCase()
  })
  .then(data => {
    console.log(data)
  })

What will the output be?

  • print "SUCCESS!"
  • print "Success!"
  • print "SUCCESS!" and "SUCCESS!"
  • prints `undefined`

Hint: .then’s pass data sequentially, from return value to the next .then(value => /* handle value */).

A return is key in order to pass a value to the next .then.

Flow between .then’s and .catch’s

Promise.resolve('Success!')
  .then(() => {
    throw Error('Oh noes!')
  })
  .catch(error => {
    return 'actually, that worked'
  })
  .then(data => {
    throw Error('The fails!')
  })
  .catch(error => console.log(error.message))

What will the output be?

  • print "Oh noes!" and "The fails!"
  • print "Oh noes!"
  • print "The fails!"
  • print "actually, that worked"
  • nothing prints

annotated-code/question-9-4.gif

Unless otherwise noted, all content is copyright Dan Levy 2014-1019.