Async & Promisesmedium

Guard against double resolve/reject in wrappers

When adapting callback APIs to promises, demonstrate how to prevent accidental multiple settle calls.

Asked at Stripe, TikTok, Apple

#promises#wrappers#callbacks#pitfalls

Answer

function fromCallback(register) {
  return new Promise((resolve, reject) => {
    let settled = false

    const onceResolve = (value) => {
      if (settled) return
      settled = true
      resolve(value)
    }

    const onceReject = (err) => {
      if (settled) return
      settled = true
      reject(err)
    }

    try {
      register(onceResolve, onceReject)
    } catch (err) {
      onceReject(err)
    }
  })
}

// Usage: adapt odd callback API
const p = fromCallback((ok, fail) => {
  ok('first')
  ok('second') // ignored safely
})
p.then(console.log) // first

Practise more Async & Promises questions →