twostep
Advanced tools
Comparing version 0.3.6 to 0.3.7
{ | ||
"name": "twostep", | ||
"version": "0.3.6", | ||
"description": "A simple control-flow library for node.JS that makes parallel execution, serial execution, and error handling painless.", | ||
"engine": [ "node >=0.2.0" ], | ||
"description": "Simple control-flow library for node.js that makes parallel execution, serial execution and error handling painless.", | ||
"version": "0.3.7", | ||
"author": "2do2go team <dev.2do2go@gmail.com>", | ||
"license": "MIT", | ||
"repository": { | ||
@@ -10,2 +11,5 @@ "type" : "git", | ||
}, | ||
"keywords": [ | ||
"control", "flow", "step", "async", "sync" | ||
], | ||
"devDependencies" : { | ||
@@ -16,5 +20,5 @@ "mocha": "1.8.1", | ||
"scripts": { | ||
"test": "./node_modules/mocha/bin/mocha ./spec/*.spec.js" | ||
"test": "mocha spec --reporter spec" | ||
}, | ||
"main": "lib/twoStep" | ||
} |
274
README.md
@@ -1,193 +0,127 @@ | ||
TwoStep | ||
======= | ||
A simple control-flow library for node.JS that makes parallel execution, | ||
serial execution, and error handling painless. Based on gist https://gist.github.com/1524578 | ||
# TwoStep | ||
Differents with gist: | ||
* test coverage was added | ||
* try...catch blocks for all steps | ||
* useful wrappers: throwIfError and simple | ||
* Steppy was added (details below) | ||
* group, that was created with makeGroup may not be called and in this case it will pass empty array to the next step | ||
Is a simple control-flow library for node.js that makes serial execution, | ||
parallel execution and error handling painless. Inspired by [step] twostep was | ||
based on Tim Caswell ([step] author) [gist](https://gist.github.com/1524578), | ||
but later it was refactored and almost totally rewritten. Twostep follows and | ||
extends the ideas behind the [step]. | ||
Installation | ||
----------- | ||
Features | ||
npm install twostep | ||
* serial and parallel (with results grouping support) execution | ||
* simple error handling | ||
* simplified error handling for common use case (when error handled at the | ||
last step) using Steppy (see details below) | ||
* ability to pass the arbitrary values between steps (using `this.pass()`) | ||
* pure js code (no dependencies, < 200 lines of code) | ||
* good test coverage | ||
* super battle-tested (we ubiquitously use twostep in a big project | ||
(50 000+ lines of code)) | ||
Usage | ||
----------- | ||
All callbacks are executing in theirs steps. | ||
## Installation | ||
var TwoStep = require('twostep').Step, | ||
FS = require('fs'); | ||
```sh | ||
npm install twostep | ||
``` | ||
Step( | ||
function one() { | ||
this.pass(__filename + ".bak"); | ||
FS.readFile(__filename, 'utf8', this.slot()); | ||
}, | ||
function two(err, target, contents) { | ||
if (err) throw err; | ||
this.pass(target); | ||
FS.writeFile(target, contents, this.slot()) | ||
}, | ||
function three(err, target) { | ||
if (err) throw err; | ||
console.log("%s written to successfully", target); | ||
FS.readdir(__dirname, this.slot()); | ||
}, | ||
function four(err, fileNames) { | ||
if (err) throw err; | ||
this.pass(fileNames); | ||
var group = this.makeGroup(); | ||
fileNames.forEach(function (filename) { | ||
FS.stat(filename, group.slot()); | ||
}); | ||
}, | ||
function five(err, fileNames, stats) { | ||
if (err) throw err; | ||
this.pass(fileNames.filter(function (name, i) { | ||
return stats[i].isFile(); | ||
})); | ||
var group = this.makeGroup(); | ||
stats.forEach(function (stat, i) { | ||
if (stat.isFile()) FS.readFile(fileNames[i], 'utf8', group.slot()); | ||
}); | ||
}, | ||
function six(err, fileNames, contents) { | ||
if (err) throw err; | ||
var merged = {}; | ||
fileNames.forEach(function (name, i) { | ||
merged[name] = contents[i].substr(0, 80); | ||
}); | ||
console.log(merged); | ||
} | ||
); | ||
This can be some simple if we will use wrappers. | ||
## Usage | ||
var Step = require('twostep').Step, | ||
FS = require('fs'); | ||
All steps (functions) passed to the `Step` will be executed in series. Inside | ||
each step `this.slot()` for wating of async call, `this.pass()` for | ||
passing value to the next step or `this.makeGroup()` for creating group (for | ||
calling `slot()` or `pass()` for the group and having results | ||
grouped to array) can be called. If error is occured inside step it will be | ||
passed to the next step as first argument. First argument of the step is | ||
always an error (falsy if no error), subsequent arguments - results of calls | ||
accepted by `this.pass()`, `this.slot()` or `this.makeGroup()` in the order | ||
they were called at previous step. | ||
Step( | ||
Step.simple(function() { | ||
this.pass(__filename + ".bak"); | ||
FS.readFile(__filename, 'utf8', this.slot()); | ||
}), | ||
Step.throwIfError(function(err, target, contents) { | ||
this.pass(target); | ||
FS.writeFile(target, contents, this.slot()) | ||
}), | ||
Step.throwIfError(function(err, target) { | ||
console.log("%s written to successfully", target); | ||
FS.readdir(__dirname, this.slot()); | ||
}), | ||
Step.throwIfError(function(err, fileNames) { | ||
this.pass(fileNames); | ||
var group = this.makeGroup(); | ||
fileNames.forEach(function(filename) { | ||
FS.stat(filename, group.slot()); | ||
}); | ||
}), | ||
Step.throwIfError(function(err, fileNames, stats) { | ||
this.pass(fileNames.filter(function(name, i) { | ||
return stats[i].isFile(); | ||
})); | ||
console.log(fileNames) | ||
var group = this.makeGroup(); | ||
stats.forEach(function(stat, i) { | ||
if (stat.isFile()) { | ||
FS.readFile(fileNames[i], 'utf8', group.slot()); | ||
} | ||
}); | ||
}), | ||
Step.throwIfError(function(err, fileNames, contents) { | ||
var merged = {}; | ||
fileNames.forEach(function (name, i) { | ||
merged[name] = contents[i].substr(0, 80); | ||
}); | ||
console.log(merged); | ||
}), | ||
Step.simple(function(err) { | ||
if (err) { | ||
console.log('Do something to handle error'); | ||
} | ||
}) | ||
); | ||
```js | ||
Wrapper Step.throwIfError free you of all time writing | ||
var Step = require('twostep').Step, | ||
fs = require('fs'); | ||
if (err) throw err; | ||
Step( | ||
function() { | ||
// pass filename to the next step as second argument (error always first) | ||
this.pass(__filename + '.bak'); | ||
// read the file content, it will be passed as third argument (because | ||
// this.pass was called before) | ||
fs.readFile(__filename, 'utf8', this.slot()); | ||
}, | ||
function(err, bakFile, content) { | ||
// if we have an error, throw it to skip this step | ||
if (err) throw err; | ||
this.pass(bakFile); | ||
fs.readdir(__dirname, this.slot()); | ||
fs.writeFile(bakFile, content, this.slot()) | ||
// `readdir` and `writeFile` will be exeuted in parallel when both of | ||
// them done next step will be called | ||
}, | ||
function(err, bakFile, dirContent) { | ||
if (err) throw err; | ||
console.log('%s successfully written', bakFile); | ||
this.pass(dirContent); | ||
// make the group | ||
var group = this.makeGroup(); | ||
// wait for ordered results using group.slot() - all results | ||
// will be passed as an array with same order (as at calls) | ||
dirContent.forEach(function(name) { | ||
fs.stat(name, group.slot()); | ||
}); | ||
}, | ||
function(err, dirContent, stats) { | ||
if (err) throw err; | ||
var fileNames = dirContent.filter(function(name, i) { | ||
return stats[i].isFile(); | ||
}); | ||
console.log('files in dir: %s', fileNames); | ||
// don't call next step manually, it's the last step if no error | ||
}, | ||
function(err) { | ||
// this step will be called only if an error was occured at any step | ||
// above, so here we can handle the error. | ||
console.log('Error occured: ', err.stack || err); | ||
process.exit(1); | ||
} | ||
); | ||
All steps throwIfError will be skipped. Error just will be passed through the steps. | ||
To handle it you can use | ||
``` | ||
Step.simple(function(err) {}) | ||
In the example above we did `if (err) throw err;` at the start of every step to | ||
pass the error (if it exists) to the next step for handle the error at the last | ||
step. We can simply avoid writing this annoying line using `Steppy` (can be | ||
imported as `var Steppy = require('twostep').Steppy`) instead of | ||
`Step`. `Steppy` automatically wraps every single step with error check and | ||
calls the last step if error occurs. | ||
or something other function, that get error in first parameter. | ||
It's very usefull for common mechanism of error handling. | ||
Created group has same api as `this` but if `pass()` or `slot()` was | ||
not called for the group empty array will be passed to the next step as group result. | ||
If `this.pass()`, `this.slot()` or `this.makeGroup()` will not be called then | ||
next step will never be called. | ||
Or, it can be even easier if we will use Steppy instead of Step. It wraps all functions | ||
except the last one in throwIfError wrapper by default, because it's the most common | ||
usage of Step. | ||
var Steppy = require('twostep').Steppy, | ||
FS = require('fs'); | ||
## Tests | ||
Steppy( | ||
function() { | ||
this.pass(__filename + ".bak"); | ||
FS.readFile(__filename, 'utf8', this.slot()); | ||
}, | ||
function(err, target, contents) { | ||
this.pass(target); | ||
FS.writeFile(target, contents, this.slot()) | ||
} | ||
function(err, target) { | ||
console.log("%s written to successfully", target); | ||
FS.readdir(__dirname, this.slot()); | ||
}, | ||
function(err, fileNames) { | ||
this.pass(fileNames); | ||
var group = this.makeGroup(); | ||
fileNames.forEach(function(filename) { | ||
FS.stat(filename, group.slot()); | ||
}); | ||
}, | ||
function(err, fileNames, stats) { | ||
this.pass(fileNames.filter(function(name, i) { | ||
return stats[i].isFile(); | ||
})); | ||
console.log(fileNames) | ||
var group = this.makeGroup(); | ||
stats.forEach(function(stat, i) { | ||
if (stat.isFile()) { | ||
FS.readFile(fileNames[i], 'utf8', group.slot()); | ||
} | ||
}); | ||
}, | ||
function(err, fileNames, contents) { | ||
var merged = {}; | ||
fileNames.forEach(function (name, i) { | ||
merged[name] = contents[i].substr(0, 80); | ||
}); | ||
console.log(merged); | ||
}, | ||
function(err) { | ||
// if we're here then we definitely have an error | ||
console.log('Do something to handle error'); | ||
} | ||
); | ||
into cloned repository run | ||
Test | ||
------ | ||
In project folder just run: | ||
```sh | ||
npm install | ||
``` | ||
npm install | ||
after installtion run | ||
After installtion run: | ||
```sh | ||
npm test | ||
``` | ||
npm test | ||
## License | ||
MIT | ||
[step]: https://github.com/creationix/step |
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found
Found 1 instance in 1 package
15
0
1
20559
128