Javascript Promises

Published: Wednesday, Feb 8, 2017 Last modified: Thursday, Nov 14, 2024

Promises FAQ

Promises with AWS

How do i implement a reject on a thrown error?

return Promise.resolve().then(() => {
  if (!isGood) throw new Error('a wrench')
  return doneStuff
})

Refactoring example

Bad:

function foo(data) {
	return new Promise((resolve, reject) => {
		console.log("debug data", data)
		let video = {}
		if (data.Item) {
			video = data.Item
		} else {
			video = data
		}
		console.log("debug video", video)
		resolve(video)
	})
}

foo({ id: 12, title: "Back to the future"})
.then((output) => console.log(output))

Really bad (i.e. non-working) when using const btw!

Good:

function foo (data) {
	return Promise.resolve().then(() => {
		console.log("debug data", data)
		return data.Item || data
	})
}

Or event just:

function foo (data) {
  return Promise.resolve().then(() => data.Item || data)
}

prefer const

From Tim Oxley: seems a shame to lose benefits of const due to conditional initialisation. Instead of if/else + let I generally go for const + || in cases like the above, or a ternary :

// ternary
const thing = someCondition ? valueIfTrue : valueIfFalse
// multi-line conditional
const thing = (
  multi &&
  line &&
  conditional
)
? valueIfTrue
: valueIfFalse

Single line arrows

for single line arrows, you don’t need the curlies or the return:

const a = () => { return get(uuidgen) }
// is equivalent to:
const b = () => get(uuidgen)

i.e. right hand side of the arrow can be a block or an expression

Promise refactoring

return Promise.resolve().then(() => { return })

is the same as:

return Promise.resolve()

Remember with promise you can resolve to either a promise or a value. if you resolve to a promise, the resolved value of the current promise will become the value resolved from the returned/resolved promise.

These are (mostly) equivalent, and will both resolve to 3

Promise.resolve().then(() => {
  return 3
})

Promise.resolve().then(() => {
  return Promise.resolve(3)
})

These are also (mostly) equivalent:

Promise.resolve()

Promise.resolve().then(() => {})

Promise.resolve().then(() => { return })

Promise.resolve().then(() => {
  return Promise.resolve(undefined)
})

Two callbacks are bad!

function cb () {
  console.log('called');
  throw new Error('bad')
}

Promise.resolve()
.then(() => cb(null))
.catch(cb)

Correct is:

Promise.resolve()
.then(() => cb(null), cb)

Remember, then takes a second argument, e.g. p.then(onResolved, onRejected), which fits perfectly with the errback signature callback(err)!

More short hand action

foo.js

function foo (data) {
	return new Promise((resolve, reject) => {
	  if (data.sdadas.dasdsada) { resolve(2) }
	  resolve(1)
	})
}
module.exports = foo

main.js:

const foo = require('./foo.js')

foo()
//.then((data) => { console.log(data) })
.then(console.log)
// .catch((e) => { console.log("oh dear", e) } )
.catch(console.log)