src/core/pSeries.js
function pSeries (iterable, bail) {
  const result = []
  const iterableLength = iterable.length

  function noop (index, bail) {
    /**
     * End of promises
     */
    if (index >= iterableLength) {
      return Promise.resolve(result)
    }

    return iterable[index]
      .then((output) => {
        result.push(onResolved(output))
        return noop(index + 1, bail)
      })
      .catch((error) => {
        result.push(onRejected(error))

        /**
         *
         *  When bail is false, we continue after rejections
         *  too.
         */
        if (!bail) {
          return noop(index + 1, bail)
        }

        /**
         *  Otherwise we resolve the promise
         */
        return Promise.resolve(result)
      })
  }

  return noop(0, bail)
}
function pSeries (iterable, bail) {
  const result = []
  const iterableLength = iterable.length

  function noop (index, bail) {
    /**
     * End of promises
     */
    if (index >= iterableLength) {
      return Promise.resolve(result)
    }

    return iterable[index]
      .then((output) => {
        result.push(onResolved(output))
        return noop(index + 1, bail)
      })
      .catch((error) => {
        result.push(onRejected(error))

        /**
         *
         *  When bail is false, we continue after rejections
         *  too.
         */
        if (!bail) {
          return noop(index + 1, bail)
        }

        /**
         *  Otherwise we resolve the promise
         */
        return Promise.resolve(result)
      })
  }

  return noop(0, bail)
}
function pSeries ( iterable , bail ) { const result = [ ] const iterableLength = iterable . length function noop ( index , bail ) { /**
     * End of promises
     */ if ( index >= iterableLength ) { return Promise . resolve ( result ) } return iterable [ index ] . then ( ( output ) => { result . push ( onResolved ( output ) ) return noop ( index + 1 , bail ) } ) . catch ( ( error ) => { result . push ( onRejected ( error ) ) /**
         *
         *  When bail is false, we continue after rejections
         *  too.
         */ if ( ! bail ) { return noop ( index + 1 , bail ) } /**
         *  Otherwise we resolve the promise
         */ return Promise . resolve ( result ) } ) } return noop ( 0 , bail ) }
Here we run an array of promises in sequence until the last
promise is finished.

When `bail=true`, it will break the chain when first promise returns
the error/exception.

## Why serial?
Since the validations have to be executed one after the other, the
promises execution has to be in sequence

## Why wait for all promises?
The `validateAll` method of the library allows to run all validations,
even when they fail. So this method handles that too.

## Note
This method will never reject, instead returns an array of objects, which
has `rejected` and `fullFilled` properties to find whether the promise
was rejected or not.

@method pSeries

@param {Array} iterable
@param {Boolean} bail

@return {Object[]}  result - Array of objects holding promises results
@property {Boolean} result.fullFilled
@property {Boolean} result.rejected
@property {Mixed}   result.value - Resolved value if fullFilled
@property {Mixed}   result.reason - Error value if rejected

@example
pSeries([p1, p2])
.then((result) => {
const errors = result.filter((item) => item.rejected)
if (errors.length) {
console.log(errors)
}
})

// stopping after first failure
pSeries([p1, p2], true)
.then((result) => {
const errors = result.filter((item) => item.rejected)
if (errors.length) {
console.log(errors[0])
}
})
Here we run an array of promises in sequence until the last promise is finished .