Skip to content

Commit

Permalink
Refactor.
Browse files Browse the repository at this point in the history
* Exports a `Runner` to specify options.
* Always return a promise.
* Arguments are ignored by default.
  • Loading branch information
zoubin committed Dec 7, 2015
1 parent 8ddfdfc commit 3468c13
Show file tree
Hide file tree
Showing 22 changed files with 1,019 additions and 446 deletions.
3 changes: 1 addition & 2 deletions .eslintrc
Expand Up @@ -28,13 +28,12 @@ rules:
use-isnan: 2
valid-typeof: 2
no-unexpected-multiline: 2
no-cond-assign: 2
no-constant-condition: 2
no-control-regex: 2
no-debugger: 2
# code style
consistent-return: 0
curly: 2
curly: [2, "multi-line"]
default-case: 2
dot-notation: 2
dot-location: [2, "property"]
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -3,3 +3,4 @@
npm-debug.log
build/
coverage/
.nyc_output/
6 changes: 3 additions & 3 deletions .npmignore
@@ -1,6 +1,6 @@
npm-debug.log
changelog.md
coverage
example
test
coverage/
example/
test/
.*
209 changes: 129 additions & 80 deletions README.md
@@ -1,34 +1,35 @@
# callback-sequence
Make a new callback to run callbacks in sequence or parallel.

[![version](https://img.shields.io/npm/v/callback-sequence.svg)](https://www.npmjs.org/package/callback-sequence)
[![status](https://travis-ci.org/zoubin/callback-sequence.svg?branch=master)](https://travis-ci.org/zoubin/callback-sequence)
[![dependencies](https://david-dm.org/zoubin/callback-sequence.svg)](https://david-dm.org/zoubin/callback-sequence)
[![devDependencies](https://david-dm.org/zoubin/callback-sequence/dev-status.svg)](https://david-dm.org/zoubin/callback-sequence#info=devDependencies)

Make a new callback to run callbacks in sequence or parallel.

Callbacks can be made async like [gulp tasks](https://github.com/gulpjs/gulp/blob/master/docs/API.md#fn).

## Example

```javascript
var sequence = require('callback-sequence')
var thunkify = require('callback-sequence')

var Readable = require('stream').Readable
var gulp = require('gulp')

gulp.task('sequence', sequence(
gulp.task('sequence', thunkify(
sync, async, promise, stream
))

gulp.task('parallel', sequence(
gulp.task('parallel', thunkify(
[sync, async, promise, stream]
))

gulp.task('parallel-nested', sequence(
gulp.task('parallel-nested', thunkify(
// `async` and `promise` will be run in parallel
sync, [async, promise], stream
))

gulp.task('sequence-nested', sequence(
gulp.task('sequence-nested', thunkify(
// `async` and `promise` will be run in sequence
[sync, [async, promise], stream]
))
Expand All @@ -54,143 +55,191 @@ function stream() {

## API

### cb = sequence(...tasks)
Return a callback to run the specified tasks in appearance order.
### cb = thunkify(...tasks)
Return a callback to run the specified tasks in the appearance order.

`cb` will return a promise.

```javascript
var sequence = require('callback-sequence')
var res = []
thunkify(
function () {
res.push(1)
},
function (next) {
process.nextTick(function () {
res.push(2)
next()
})
},
function () {
return Promise.resolve().then(function () {
res.push(3)
})
}
)()
.then(function () {
// [1, 2, 3]
console.log(res)
})

sequence(
function () { console.log(1) },
```

### thunkify.run(tasks)
It just runs `tasks` like you call the function returned by `thunkify`

**NOTE**: if some task is an array of sub-tasks, they will be run in parallel.

```javascript
var run = require('callback-sequence').run

var res = []
run([
function () { res.push(1) },
[
function (cb) {
setTimeout(function() {
console.log(3)
res.push(3)
cb()
}, 0)
},
function () {
return new Promise(function (resolve) {
process.nextTick(function () {
console.log(2)
res.push(2)
resolve()
})
})
},
],
function () { console.log(4) },
)().then(function () {
console.log('DONE')
})

// 1
// 2
// 3
// 4
// DONE


```

### res = sequence.run(tasks, initialArgs)
Run the specified tasks in sequence.

* `tasks`: Type: `Array`. If a task is specified as an array of subtasks, those tasks will be run with `sequence.parallel`
* `initialArgs`: Type: `Array`. Arguments passed to the first task.
* `res`: Type: `Promise`. Resolves to an array of results created by the last task.

```javascript
var sequence = require('callback-sequence')

run([
function (a, b) {
t.same([a, b], [1, 2])
return a + b
},
function (res, cb) {
t.same(res, 3)
setTimeout(function() {
cb(null, res, 4)
}, 0)
},
], [1, 2])
.then(function (res) {
// [3, 4]
function () { res.push(4) },
]
)
.then(function () {
// [1, 2, 3, 4]
console.log(res)
})

```

Actually, you can add callbacks dynamically:
Callbacks an be added dynamically:

```javascript
var run = require('callback-sequence').run

var count = 5
var tasks = []

function task(res, next) {
var res = []
function task(next) {
process.nextTick(function () {
res.push(count)
if (--count > 0) {
tasks.push(task)
}
next(null, res)
next()
})
}
run(tasks, [[]]).then(function (res) {
// [ [5, 4, 3, 2, 1] ]
run(tasks).then(function () {
// [5, 4, 3, 2, 1]
console.log(res)
})

tasks.push(task)

```

### res = sequence.parallel(tasks, initialArgs)
### thunkify.parallel(tasks)
Run the specified tasks in parallel.

* `tasks`: Type: `Array`. If a task is specified as an array of subtasks, those tasks will be run with `sequence.run`.
* `initialArgs`: Type: `Array`. Arguments passed to all tasks.
* `res`: Type: `Promise`. Resolves to an array of results created by the call tasks.
**NOTE**: if some task is an array of sub-tasks, they will be run in sequence.

```javascript
var parallel = require('callback-sequence').parallel

var res = []
parallel([
function () { console.log(1) },
function () { res.push(1) },
[
function (cb) {
setTimeout(function() {
console.log(3)
cb()
}, 0)
},
function () {
return new Promise(function (resolve) {
process.nextTick(function () {
console.log(2)
resolve()
})
return Promise.resolve().then(function () {
res.push(4)
})
},
function () { res.push(5) },
],
function () { console.log(4) },
function (cb) {
setTimeout(function() {
res.push(3)
cb()
}, 0)
},
function (cb) {
res.push(2)
cb()
},
]
)
.then(function () {
console.log('DONE')
// [1, 2, 4, 5, 3]
console.log(res)
})

// 1
// 4
// 3
// 2
// DONE
```

### Runner = thunkify.Runner(opts)
Return a new runner instance, with the following methods:

* `sequence`: just like `thunkify.run`
* `parallel`: just like `thunkify.parallel`
* `thunkify`: just like `thunkify`

#### opts

##### input
Specify whether to pass the results of the previous callback to the next as arguments.

Type: `Boolean`

Default: `true`

```javascript
var Runner = require('callback-sequence').Runner

var runner = Runner({ input: true })

runner.thunkify(
function (a, b) {
// 3
return a + b
},
function (sum, next) {
process.nextTick(function () {
// 6
next(null, sum * 2)
})
},
function (product) {
return Promise.resolve().then(function () {
// 7
return product + 1
})
}
)(1, 2)
.then(function (res) {
// [7]
console.log(res)
})


```

##### output
Specify whether to pass the results of the last callback to the final results.

Type: `Boolean`

Default: `true`

## [Changelog](changelog.md)

8 changes: 5 additions & 3 deletions example/dynamic.js
Expand Up @@ -3,16 +3,18 @@ var run = require('..').run
var count = 5
var tasks = []

function task(res, next) {
var res = []
function task(next) {
process.nextTick(function () {
res.push(count)
if (--count > 0) {
tasks.push(task)
}
next(null, res)
next()
})
}
run(tasks, [[]]).then(function (res) {
run(tasks).then(function () {
// [5, 4, 3, 2, 1]
console.log(res)
})

Expand Down
27 changes: 27 additions & 0 deletions example/input.js
@@ -0,0 +1,27 @@
var Runner = require('..').Runner

var runner = Runner({ input: true })

runner.thunkify(
function (a, b) {
// 3
return a + b
},
function (sum, next) {
process.nextTick(function () {
// 6
next(null, sum * 2)
})
},
function (product) {
return Promise.resolve().then(function () {
// 7
return product + 1
})
}
)(1, 2)
.then(function (res) {
// [7]
console.log(res)
})

0 comments on commit 3468c13

Please sign in to comment.