promise.extra
Version:
series, waterfall and more with vanilla es promise/thenable.
200 lines (148 loc) • 5.21 kB
Markdown
[](https://travis-ci.org/kaelzhang/promise.extra)
[](https://codecov.io/gh/kaelzhang/promise.extra)
<!-- optional appveyor tst
[](https://ci.appveyor.com/project/kaelzhang/promise.extra)
-->
<!-- optional npm version
[](http://badge.fury.io/js/promise.extra)
-->
<!-- optional npm downloads
[](https://www.npmjs.org/package/promise.extra)
-->
<!-- optional dependency status
[](https://david-dm.org/kaelzhang/promise.extra)
-->
# promise.extra
`Promise.series` and `Promise.waterfall` with vanilla es [`Promise`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise)/thenable
## Install
```sh
$ npm i promise.extra
```
## Usage
```js
import {
series,
waterfall,
reduce,
factory
} from 'promise.extra'
series([1, 2, 3], (prev, v) => Promise.resolve(v))
.then(values => {
console.log(values) // [1, 2, 3]
})
waterfall([1, 2, 3], 0, (prev, v) => Promise.resolve(prev + v))
.then(result => {
console.log(result) // 6
})
// The reducer could even returns non-promise values
waterfall(
[1, 2, 3],
0,
(prev, v, i) => i > 0
? prev + v
: Promise.resolve(prev + v)
)
.then(result => {
console.log(result) // 6
})
reduce([v1, v2, v3], reducer, initValue)
```
## series(tasks, reducer?): Promise
- **tasks** `Array<Task>` an array of tasks
- **Task** `any` each of the tasks could be anything.
- **reducer** `?ReducerFunction` the reducer which will process each `task` and returns either a `Promise` or any value.
Always returns a `Promise`.
```ts
function ReducerFunction (
prev: any,
task: Task,
index: number,
tasks
): Promise | any
```
- **prev** The result value of the last task which processed by the `reducer`. If the return value of the last reducer is an `Promise`, `prev` will be the value inside the promise.
- **task** The current task.
- **index** The index of task
- **tasks** Just the `tasks` argument of function `series`
The default value of `reducer` is:
```js
(prev, currentValue) => currentValue
```
`currentValue` is one of the `Task`s, and each `Task` could be a `Promise` or a normal JavaScript variable or object.
If you want each of the `Task`s to be a factory function that returns a `Promise` or normal values, and execute each value inside the reducer, just define the reducer as:
```js
function reducer (prev, factory) {
// If `series` is invoked by `series.call(this, ...args)`,
// reducer could share the `this` object.
return factory.call(this, prev)
}
```
## waterfall(tasks, initValue, reducer?)
- **tasks** `Array<PromiseFactory>`
- **PromiseFactory** `Function(x): Promise` a factory function which receives a parameter and returns a `Promise`
- **initValue** `any | undefined` optional initial value which will be passed into the first factory function.
- **reducer**
Always returns `Promise`.
## reduce(tasks, reducer, initValue)
- **tasks**
- **reducer** `Function(prev, factory, currentIndex, tasks): Promise` The reducer function
- **initValue** `any | undefined` if no initial value is supplied, `undefined` will be used.
Always returns `Promise`
## findIndex(tasks, matcher, reducer?)
## find(tasks, matcher, reducer?)
## indexOf(tasks, value, reducer?)
## some(tasks, reducer?)
## every(tasks, reducer?)
Each of the methods is similar to the behavior of `Array.prototype.<method>`.
## factory(promise)
- **promise** `Promise|PromiseLike`
Creates the new `reduce`, `series`, `waterfall` with the `Promise` which can be `bluebird`, [`promise-faker`](https://github.com/kaelzhang/promise-faker) or something.
```js
import Promise from 'promise-faker'
const {
series
} = factory(Promise)
series(tasks)
```
## Examples
### Usage of `reducer`
```js
const nickName = 'Steve'
// Suppose there are two async functions to check the nickName
series(
[checkNickNameSyntax, remoteCheckUnique],
(prev, factory) => factory(nickName)
)
```
### The `this` Object
```js
function lessThan10 (notThrow) {
if (this.number < 10) {
this.number ++
return true
}
if (notThrow) {
return false
}
return Promise.reject('larger than 10')
}
series.call({number: 10}, [lessThan10, lessThan10])
// Reject
series.call({number: 1}, [lessThan10, lessThan10])
// Promise.resolve<true>
series.call({number: 10},
[lessThan10, lessThan10],
function (prev, factory) {
// 1. Be careful that you should use `factory.call` here
// to pass the `this` object to `factory`
// 2. use the parameter `notThrow`
return factory.call(this, true)
}
)
// Promise.resolve<false>
```
## Upgrade Guide
### 3.x -> 4.x
`promise.extra` no longer supports node < 6 since `4.0.0`. For old node versions, `require('promise.extra/legacy')`
## License
MIT