tunnckoCore / ideas

:notebook: My centralized place for ideas, thoughts and todos. Raw, PoC implementations and so on... :star:
http://j.mp/1stW47C
6 stars 0 forks source link

promises play #61

Closed tunnckoCore closed 7 years ago

tunnckoCore commented 7 years ago
'use strict'

var delay = require('delay')
var foo = 'default'

// parallel: 5, 1, 4, 3, 2
const arr = [
  function one () {
    return delay(200).then(() => {
      console.log(1)
      return 123
    })
  },
  Promise.resolve('foobar'),
  function two () {
    return delay(1500).then(() => {
      console.log(2)
      foo = 'oookey'
      return 345
    })
  },
  delay(10).then(() => 'zero'),
  function three () {
    return delay(400).then(() => {
      console.log(3, foo)
      coffffnsole.log(3)
      return 567
    })
  },
  function four () {
    return delay(250).then(() => {
      console.log(4)
      return 789
    })
  },
  'abc',
  function five () {
    return delay(100).then(() => {
      console.log(5)
      return 444
    })
  }
]

function eachParallel (iterable, mapper, opts) {
  return new Promise(function (resolve, reject) {
    let doneCount = 1
    const results = []
    const options = mapper && typeof mapper === 'object'
      ? mapper
      : (opts && typeof opts === 'object' ? opts : {})

    function handle (name, index) {
      return function (val) {
        const ret = {}

        ret[name] = val
        ret.index = index

        if (typeof mapper === 'function') {
          results.push(mapper(ret, ret.index, item))
          return
        }

        results.push(options.flat ? ret[name] : ret)
        if (!options.settle && ret.reason) {
          throw val
        }
      }
    }

    iterable.forEach(function (item, index) {
      let promise = typeof item === 'function'
        ? item()
        : Promise.resolve(item)

      promise.then(handle('value', index), handle('reason', index))
        .then(function () {
          if (doneCount++ === iterable.length) {
            resolve(results)
          }
        }, options.settle ? null : reject)
    })
  })
}

function eachSerial (iterable, mapper, opts) {
  return new Promise(function (resolve, reject) {
    const iterator = iterable[Symbol.iterator]()
    const results = []
    const options = mapper && typeof mapper === 'object'
      ? mapper
      : (opts && typeof opts === 'object' ? opts : {})

    function next (index) {
      const item = iterator.next()

      if (item.done) {
        return resolve(results)
      }

      function handle (name) {
        return (val) => {
          const idx = results.length
          const ret = {}

          ret[name] = val
          ret.index = idx

          if (typeof mapper === 'function') {
            results.push(mapper(ret, ret.index, item))
            return
          }

          results.push(options.flat ? ret[name] : ret)

          if (!options.settle && ret.reason) {
            throw val
          }
        }
      }

      let promise = typeof item.value === 'function'
        ? item.value()
        : Promise.resolve(item.value)

      promise
        .then(handle('value'), handle('reason'))
        .then(() => next(index + 1))
        .catch((err) => {
          if (!options.settle) {
            reject(err)
            return
          }
          next(index + 1)
        })
    }

    next(0)
  })
}

// @TODO: fix parallel handling when err

eachParallel(arr)
// eachSerial(arr)

.then(function (res) {
  console.log('end ok', res)
}, function (err) {
  console.log('end fail', err)
})
tunnckoCore commented 7 years ago

last shot

'use strict'

var delay = require('delay')
var foo = 'default'

// parallel: 5, 1, 4, 3, 2
const arr = [
  function one () {
    return delay(200).then(() => {
      console.log(1)
      return 123
    })
  },
  Promise.resolve('foobar'),
  function two () {
    return delay(1500).then(() => {
      console.log(2)
      foo = 'oookey'
      return 345
    })
  },
  delay(10).then(() => 'zero'),
  function three () {
    return delay(400).then(() => {
      console.log(3, foo)
      coffffnsole.log(3)
      return 567
    })
  },
  function four () {
    return delay(250).then(() => {
      console.log(4)
      return 789
    })
  },
  'abc',
  function five () {
    return delay(100).then(() => {
      console.log(5)
      return 444
    })
  }
]

function eachParallel (iterable, mapper, opts) {
  return new Promise(function (resolve, reject) {
    if (typeof iterable !== 'object') {
      return reject(new TypeError('expect `iterable` to be array, iterable or object'))
    }

    let doneCount = 1
    const results = []
    const options = mapper && typeof mapper === 'object'
      ? mapper
      : (opts && typeof opts === 'object' ? opts : {})

    function handle (name, index) {
      return function (val) {
        const ret = {}

        ret[name] = val
        ret.index = parseInt(index)

        if (typeof mapper === 'function') {
          results.push(mapper(ret, ret.index, item))
          return
        }

        results.push(options.flat ? ret[name] : ret)
        if (!options.settle && ret.reason) {
          throw val
        }
      }
    }

    for (let index in iterable) {
      let next = null // diff
      let item = iterable[index]
      let promise = typeof item === 'function'
        ? item()
        : Promise.resolve(item)

      promise
        .then(handle('value', index), handle('reason', index))
        .then(function () {
          if (doneCount++ === iterable.length) {
            resolve(results)
          }
          next && next(index + 1)
        })
        .catch((err) => {
          if (!options.settle) {
            reject(err)
            return
          }
          next && next(index + 1)
        })
  })
}

function eachSerial (iterable, mapper, opts) {
  return new Promise(function (resolve, reject) {
    if (typeof iterable !== 'object') {
      return reject(new TypeError('expect `iterable` to be array, iterable or object'))
    }

    let doneCount = 1
    const results = []
    const options = mapper && typeof mapper === 'object'
      ? mapper
      : (opts && typeof opts === 'object' ? opts : {})

    function handle (name, index) {
      return function (val) {
        const ret = {}

        ret[name] = val
        ret.index = index

        if (typeof mapper === 'function') {
          results.push(mapper(ret, ret.index, item))
          return
        }

        results.push(options.flat ? ret[name] : ret)
        if (!options.settle && ret.reason) {
          throw val
        }
      }
    }

    function next (index) {
      let item = iterable[index]
      let promise = typeof item === 'function'
        ? item()
        : Promise.resolve(item)

      promise
        .then(handle('value', index), handle('reason', index))
        .then(function () {
          if (doneCount++ === iterable.length) {
            resolve(results)
          }
          next(index + 1)
        })
        .catch((err) => {
          if (!options.settle) {
            reject(err)
            return
          }
          next(index + 1)
        })
    }

    next(0)
  })
}

eachParallel(arr, {settle: true})
// eachSerial(arr, {settle: true})
.then(function (res) {
  console.log('end ok', res)
  process.exit(0)
}, function (err) {
  console.log('end fail', err)
  process.exit(1)
})

// Promise.all(arr.map(function (item) {
//   return typeof item === 'function' ? item() : item
// }))
// .then(function (res) {
//   console.log('end ok', res)
// }, function (err) {
//   console.log('end fail', err)
// })
tunnckoCore commented 7 years ago

check if using asyncs map/mapSeries, that "bug" exists

tunnckoCore commented 7 years ago

implement hooks, through options - start, beforeEach, afterEach, finish

tunnckoCore commented 7 years ago

continues https://github.com/tunnckoCore/each-promise