Home Blog CV Projects Patterns Notes Book Colophon Search

Settled

function settled (promiseObject) {
  if (Object.keys(promiseObject).length === 0) {
    return Promise.resolve({})
  }
  return new Promise((resolve, reject) => {
    let failed = 0
    let succeeded = 0
    const fullResults = {}
    const success = {}
    const pairs = Object.entries(promiseObject)
    const length = pairs.length
    pairs.forEach(([key, value]) => {
      Promise.resolve(value)
      .then((result) => {
        succeeded++
        fullResults[key] = {ok: true, result}
        if (failed === 0) {
          success[key] = result
        }
      })
      .catch((error) => {
        failed++
        fullResults[key] = {ok: false, error}
      })
      .then(() => {
        if ((failed + succeeded) === length) {
          if (failed) {
            reject(fullResults)
          } else {
            resolve(success)
          }
        }
      })
    })
  })
}

Example:

settled({one: '1', two: '2'}).then((res) => {
  console.log(res)
})

settled({one: '1', two: Promise.reject('2')}).catch((res) => {
  console.log(res)
})

Gives:

{ one: '1', two: '2' }
{ one: { ok: true, result: '1' },
  two: { ok: false, error: '2' } }

And a synchronous version that gives the same structures:

function all (readyToRunWithSpecs) {
  if (Object.keys(readyToRunWithSpecs).length === 0) {
    return {}
  }
  let failed = 0
  let succeeded = 0
  const fullResults = {}
  const success = {}
  const pairs = entries(readyToRunWithSpecs)
  pairs.forEach(([key, [fn, spec]]) => {
    let result
    let ok = true
    try {
      result = fn(spec)
      succeeded++
      fullResults[key] = {ok, result}
    } catch (error) {
      ok = false
      failed++
      fullResults[key] = {ok, error}
    }
    if (failed === 0) {
      success[key] = result
    }
  })
  if (failed === 0) {
    return success
  } else {
    throw fullResults
  }
}

Copyright James Gardner 1996-2020 All Rights Reserved. Admin.