+24
-6
@@ -41,2 +41,3 @@ /** | ||
| callback = callback || function() {}; | ||
| var alreadyReturned; | ||
@@ -46,8 +47,25 @@ function _loop( func, callback, callDepth ) { | ||
| func( function(err, stop) { | ||
| if (err || stop) return callback(err, stop); | ||
| if (callDepth < 40) _loop(func, callback, callDepth + 1); | ||
| else setImmediate(function() { _loop(func, callback, 0); }); | ||
| if (alreadyReturned = err || stop) { | ||
| return callback(err, stop); | ||
| } | ||
| else if (callDepth < 40) { | ||
| _loop(func, callback, callDepth + 1); | ||
| } | ||
| else { | ||
| setImmediate(function() { _loop(func, callback, 0); }); | ||
| } | ||
| } ); | ||
| } | ||
| catch (e) { callback(e); } | ||
| catch (e) { | ||
| // be sure to not call the callback more than once, and do not | ||
| // inject errors from within the callback back into the callback. | ||
| // If the callback throws while still in our try/catch block, | ||
| // re-throw it as if it were coming from inside a setImmediate. | ||
| if (!alreadyReturned) { | ||
| callback(alreadyReturned = e); | ||
| } | ||
| else { | ||
| throw e; | ||
| } | ||
| } | ||
| } | ||
@@ -180,3 +198,3 @@ // note: 2.5x faster if callback is passed in to _loop vs pulled from closure | ||
| function(err, ret) { | ||
| return callback ? callback(err, mappedResults) : null; | ||
| return callback(err, mappedResults);; | ||
| } | ||
@@ -202,5 +220,5 @@ ); | ||
| function(err) { | ||
| return callback ? callback(err, pickedItems) : null; | ||
| callback(err, pickedItems); | ||
| } | ||
| ); | ||
| } |
+1
-1
| { | ||
| "name": "aflow", | ||
| "version": "0.9.0", | ||
| "version": "0.9.1", | ||
| "description": "async flow control for calls with callbacks", | ||
@@ -5,0 +5,0 @@ "license": "Apache-2.0", |
+3
-2
@@ -169,8 +169,9 @@ aflow | ||
| - document all calls | ||
| - better unit test coverage | ||
| - documented all calls | ||
| - improved unit test coverage | ||
| - allow applyVisitor() to iterate any object with a numeric length, eg `arguments` or a `Buffer` | ||
| ## Todo | ||
| - benchmark the speed of each of the primitives |
+38
-1
@@ -63,3 +63,40 @@ 'use strict'; | ||
| ); | ||
| } | ||
| }, | ||
| 'should re-throw subsequent func errors': function(t) { | ||
| t.expect(2); | ||
| try { | ||
| qflow.repeatUntil( | ||
| function(cb) { | ||
| cb(new Error("first error")); | ||
| throw new Error("second error"); | ||
| }, | ||
| function(err) { | ||
| t.equal(err.message, "first error"); | ||
| } | ||
| ); | ||
| } | ||
| catch (err) { | ||
| t.equal(err.message, "second error"); | ||
| t.done(); | ||
| } | ||
| }, | ||
| 'should re-throw callback errors': function(t) { | ||
| t.expect(1); | ||
| try { | ||
| qflow.repeatUntil( | ||
| function(cb) { | ||
| cb(null, true); | ||
| }, | ||
| function(err) { | ||
| throw new Error("callback error"); | ||
| } | ||
| ); | ||
| } | ||
| catch (err) { | ||
| t.equal(err.message, "callback error"); | ||
| t.done(); | ||
| } | ||
| }, | ||
| }, | ||
@@ -66,0 +103,0 @@ |
25642
7.09%540
10.88%177
0.57%