Comparing version
@@ -1,18 +0,20 @@ | ||
var flow = require('../lib/nue').flow; | ||
var flow = require('../index').flow; | ||
var fs = require('fs'); | ||
flow( | ||
function () { | ||
fs.readFile('LICENSE', this.async()); | ||
fs.readFile('README.md', this.async()); | ||
var myFlow = flow( | ||
function (file1, file2) { | ||
fs.readFile(file1, 'utf8', this.async()); | ||
fs.readFile(file2, 'utf8', this.async()); | ||
}, | ||
function (data1, data2) { | ||
console.log(data1.length); | ||
console.log(data2.length); | ||
this.next(data1 + data2); | ||
}, | ||
function (data) { | ||
if (this.err) throw this.err; | ||
console.log(data); | ||
console.log('done'); | ||
this.next(); | ||
}, | ||
function () { | ||
console.log('all done'); | ||
this.next(); | ||
} | ||
)(); | ||
); | ||
myFlow('file1', 'file2'); |
@@ -1,2 +0,2 @@ | ||
var flow = require('../lib/nue').flow; | ||
var flow = require('../index').flow; | ||
@@ -3,0 +3,0 @@ function sleep(flow, ms) { |
@@ -8,3 +8,3 @@ 'use strict'; | ||
exports.name = 'nue'; | ||
exports.version = '0.0.9'; | ||
exports.version = '0.1.0'; | ||
exports.flow = flow; | ||
@@ -14,3 +14,3 @@ | ||
function flow() { | ||
var functions = Array.prototype.slice.call(arguments); | ||
var functions = normalizeArgs(arguments); | ||
var deferred = function flowDeferred() { | ||
@@ -25,2 +25,9 @@ var args = Array.prototype.slice.call(arguments); | ||
function normalizeArgs(args) { | ||
if (args.length === 1 && Array.isArray(args[0])) { | ||
return args[0]; | ||
} | ||
return Array.prototype.slice.call(args); | ||
} | ||
function runFlow(tasks, caller, callerArgs, callerContext) { | ||
@@ -30,3 +37,3 @@ var flow = { | ||
data: {}, | ||
err: undefined, | ||
err: null, | ||
lastStep: null, | ||
@@ -37,6 +44,4 @@ isErrThrown: false | ||
flow.lastStep = steps[steps.length - 1]; | ||
var context = steps.length > 1 | ||
? new StepContext(steps[0], flow) | ||
: new LastStepContext(flow); | ||
context.invoke(); | ||
var context = steps.length > 1 ? new StepContext(flow, steps[0]) : new LastStepContext(flow); | ||
runStep(context); | ||
} | ||
@@ -64,9 +69,7 @@ | ||
step.events.once('done', function runNextStep() { | ||
var context = new StepContext(next, flow); | ||
context.invoke(); | ||
runStep(new StepContext(flow, next)); | ||
}); | ||
} else { | ||
step.events.once('done', function runLastStep() { | ||
var context = new LastStepContext(flow); | ||
context.invoke(); | ||
runStep(new LastStepContext(flow)); | ||
}); | ||
@@ -88,2 +91,24 @@ } | ||
function runStep(context) { | ||
if (context instanceof StepContext) { | ||
try { | ||
context.step.apply(context, context.args); | ||
} catch (e) { | ||
if (context.flow.isErrThrown) { | ||
throw e; | ||
} | ||
StepContext.prototype.end.call(context, e); | ||
} | ||
} else if (context instanceof LastStepContext) { | ||
try { | ||
context.flow.lastStep.apply(context, context.args); | ||
} catch (e) { | ||
context.flow.isErrThrown = true; | ||
throw e; | ||
} | ||
} else { | ||
throw new Error('unreachable'); | ||
} | ||
} | ||
function attachEmitter(target) { | ||
@@ -134,3 +159,3 @@ target.events = new EventEmitter(); | ||
} | ||
} | ||
}; | ||
}(args, this.asyncIndex++)); | ||
@@ -140,6 +165,7 @@ }; | ||
function StepContext(step, flow) { | ||
function StepContext(flow, step) { | ||
ContextBase.call(this); | ||
this.flow = flow; | ||
this.step = step; | ||
this.flow = flow; | ||
this.args = flow.args; | ||
this.data = flow.data; | ||
@@ -161,21 +187,10 @@ } | ||
this.flow.args = Array.prototype.slice.call(arguments, 1); | ||
var context= new LastStepContext(this.flow); | ||
context.invoke(); | ||
runStep(new LastStepContext(this.flow)); | ||
}; | ||
StepContext.prototype.invoke = function invoke() { | ||
try { | ||
this.step.apply(this, this.flow.args); | ||
} catch (e) { | ||
if (this.flow.isErrThrown) { | ||
throw e; | ||
} | ||
StepContext.prototype.end.call(this, e); | ||
} | ||
}; | ||
function LastStepContext(flow) { | ||
ContextBase.call(this); | ||
this.flow = flow; | ||
this.args = flow.args; | ||
this.data = flow.data; | ||
@@ -189,9 +204,3 @@ this.err = flow.err; | ||
this.end = noop; | ||
if (this.err) { | ||
this.flow.isErrThrown = true; | ||
throw this.err; | ||
} else { | ||
this.flow.isErrThrown = false; | ||
} | ||
this.flow.lastStep.events.emit('done', Array.prototype.slice.call(arguments)); | ||
throwOrExit(this.flow, this.err, Array.prototype.slice.call(arguments)); | ||
}; | ||
@@ -202,18 +211,12 @@ | ||
this.end = noop; | ||
throwOrExit(this.flow, err, Array.prototype.slice.call(arguments, 1)); | ||
}; | ||
function throwOrExit(flow, err, args) { | ||
if (err) { | ||
this.flow.isErrThrown = true; | ||
flow.isErrThrown = true; | ||
throw err; | ||
} else { | ||
this.flow.isErrThrown = false; | ||
} | ||
this.flow.lastStep.events.emit('done', Array.prototype.slice.call(arguments, 1)); | ||
}; | ||
LastStepContext.prototype.invoke = function invoke() { | ||
try { | ||
this.flow.lastStep.apply(this, this.flow.args); | ||
} catch (e) { | ||
this.flow.isErrThrown = true; | ||
throw e; | ||
} | ||
}; | ||
flow.isErrThrown = false; | ||
flow.lastStep.events.emit('done', args); | ||
} |
@@ -12,3 +12,3 @@ { | ||
}, | ||
"version" : "0.0.9" | ||
"version" : "0.1.0" | ||
} |
@@ -55,3 +55,4 @@ nue — An async control-flow library | ||
* `end`: Function. A function to execute a last function to end a control-flow. The first parameter is an error object. | ||
* `data`: Object : A object to share arbitrary data among functions in a control-flow. | ||
* `data`: Object : A object to share arbitrary data between functions in a control-flow. | ||
* `args`: Array : An array equivalent to `arguments` for a function. | ||
@@ -84,2 +85,3 @@ In addition to the above ones, the context of the last function has a following property. | ||
console.log(data); | ||
console.log('done'); | ||
} | ||
@@ -105,3 +107,3 @@ ); | ||
function (file1, data1, file2, data2) { | ||
console.log(file1 + ' and ' + file2 + ' have been red.'); | ||
console.log(file1 + ' and ' + file2 + ' have been read.'); | ||
this.next(data1 + data2); | ||
@@ -112,3 +114,4 @@ }, | ||
console.log(data); | ||
this.next(data); | ||
console.log('done'); | ||
this.next(); | ||
} | ||
@@ -121,3 +124,3 @@ ); | ||
`this.async` can be called in loop. | ||
Below example produces same results with above example. | ||
Following example produces same results with above example. | ||
@@ -136,4 +139,4 @@ ```js | ||
function (files) { | ||
var data = Array.prototype.slice.call(arguments, 1).join(''); | ||
console.log(files.join(' and ') + ' have been red.'); | ||
var data = this.args.slice(1).join(''); | ||
console.log(files.join(' and ') + ' have been read.'); | ||
this.next(data); | ||
@@ -144,3 +147,4 @@ }, | ||
console.log(data); | ||
this.next(data); | ||
console.log('done'); | ||
this.next(); | ||
} | ||
@@ -152,3 +156,3 @@ ); | ||
## Data Sharing Among Functions | ||
## Data Sharing Between Functions | ||
@@ -176,3 +180,3 @@ Each function in a flow can share data through `this.data`. | ||
console.log(data); | ||
console.log(this.data.file1 ' and ' + this.data.file2 ' are concatenated.'); | ||
console.log(this.data.file1 + ' and ' + this.data.file2 + ' are concatenated.'); | ||
this.next(); | ||
@@ -205,3 +209,3 @@ } | ||
// handle error | ||
... | ||
console.log(this.err); | ||
// indicate error handling completion | ||
@@ -217,3 +221,54 @@ this.err = null; | ||
myFlow('file1', 'file2'); | ||
myFlow('file1', 'non-existent-file'); | ||
``` | ||
## Unit Test with Mocha | ||
Following example shows how to test a flow and a function with Mocha. | ||
```js | ||
var flow = require('nue').flow; | ||
var fs = require('fs'); | ||
var concatFiles = flow( | ||
function (file1, file2) { | ||
fs.readFile(file1, 'utf8', this.async()); | ||
fs.readFile(file2, 'utf8', this.async()); | ||
}, | ||
function (data1, data2) { | ||
this.next(data1 + data2); | ||
} | ||
); | ||
function read(file) { | ||
fs.readFile(file, 'utf8', this.async()); | ||
} | ||
var assert = require('assert'); | ||
describe('concatFiles flow', function () { | ||
it('can be tested', function (done) { | ||
flow( | ||
concatFiles, | ||
function (data) { | ||
if (this.err) throw this.err; | ||
assert.strictEqual(data, 'FILE1FILE2'); | ||
done(); | ||
} | ||
)('file1', 'file2'); | ||
}); | ||
}); | ||
describe('read function', function () { | ||
it('can be tested', function (done) { | ||
flow( | ||
read, | ||
function (data) { | ||
if (this.err) throw this.err; | ||
assert.strictEqual(data, 'FILE1'); | ||
done(); | ||
} | ||
)('file1'); | ||
}); | ||
}); | ||
``` |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
17359
33.75%18
80%392
43.59%264
26.32%7
133.33%1
Infinity%