summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolan McMahon <caolan@caolanmcmahon.com>2014-03-28 15:02:50 +0000
committerCaolan McMahon <caolan@caolanmcmahon.com>2014-03-28 15:02:50 +0000
commit1513f799ddf351473d01172626eaa4935e11cfa1 (patch)
treead6fe1143f8154268e73134f645635a471e58fc0
parente5ae810dbe4ee82701c947bc4cf5425d0bedeef1 (diff)
parent49faae6018261a8b925d8f507784ad2789d06376 (diff)
downloadasync-1513f799ddf351473d01172626eaa4935e11cfa1.tar.gz
Merge remote-tracking branch 'ognivo/feature-seq'
Conflicts: README.md
-rw-r--r--README.md48
-rwxr-xr-xlib/async.js8
-rwxr-xr-xtest/test-async.js87
3 files changed, 141 insertions, 2 deletions
diff --git a/README.md b/README.md
index fd9282a..8f4a1c8 100644
--- a/README.md
+++ b/README.md
@@ -137,6 +137,7 @@ Usage:
* [`forever`](#forever)
* [`waterfall`](#waterfall)
* [`compose`](#compose)
+* [`seq`](#seq)
* [`applyEach`](#applyEach)
* [`applyEachSeries`](#applyEachSeries)
* [`queue`](#queue)
@@ -904,6 +905,53 @@ add1mul3(4, function (err, result) {
```
---------------------------------------
+<a name="seq" />
+### seq(fn1, fn2...)
+
+Version of the compose function that is more natural to read.
+Each following function consumes the return value of the latter function.
+
+Each function is executed with the `this` binding of the composed function.
+
+__Arguments__
+
+* functions... - the asynchronous functions to compose
+
+
+__Example__
+
+```js
+// Requires lodash (or underscore), express3 and dresende's orm2.
+// Part of an app, that fetches cats of the logged user.
+// This example uses `seq` function to avoid overnesting and error
+// handling clutter.
+app.get('/cats', function(request, response) {
+ function handleError(err, data, callback) {
+ if (err) {
+ console.error(err);
+ response.json({ status: 'error', message: err.message });
+ }
+ else {
+ callback(data);
+ }
+ }
+ var User = request.models.User;
+ asyc.seq(
+ _.bind(User.get, User), // 'User.get' has signature (id, callback(err, data))
+ handleError,
+ function(user, fn) {
+ user.getCats(fn); // 'getCats' has signature (callback(err, data))
+ },
+ handleError,
+ function(cats) {
+ response.json({ status: 'ok', message: 'Cats found', data: cats });
+ }
+ )(req.session.user_id);
+ }
+});
+```
+
+---------------------------------------
<a name="applyEach" />
### applyEach(fns, args..., callback)
diff --git a/lib/async.js b/lib/async.js
index 1a3d464..6568025 100755
--- a/lib/async.js
+++ b/lib/async.js
@@ -903,8 +903,8 @@
return async.mapSeries(counter, iterator, callback);
};
- async.compose = function (/* functions... */) {
- var fns = Array.prototype.reverse.call(arguments);
+ async.seq = function (/* functions... */) {
+ var fns = arguments;
return function () {
var that = this;
var args = Array.prototype.slice.call(arguments);
@@ -922,6 +922,10 @@
};
};
+ async.compose = function (/* functions... */) {
+ return async.seq.apply(null, Array.prototype.reverse.call(arguments));
+ };
+
var _applyEach = function (eachfn, fns /*args...*/) {
var go = function () {
var that = this;
diff --git a/test/test-async.js b/test/test-async.js
index d5b5508..539acc8 100755
--- a/test/test-async.js
+++ b/test/test-async.js
@@ -261,6 +261,93 @@ exports['compose binding'] = function (test) {
});
};
+exports['seq'] = function (test) {
+ test.expect(4);
+ var add2 = function (n, cb) {
+ test.equal(n, 3);
+ setTimeout(function () {
+ cb(null, n + 2);
+ }, 50);
+ };
+ var mul3 = function (n, cb) {
+ test.equal(n, 5);
+ setTimeout(function () {
+ cb(null, n * 3);
+ }, 15);
+ };
+ var add1 = function (n, cb) {
+ test.equal(n, 15);
+ setTimeout(function () {
+ cb(null, n + 1);
+ }, 100);
+ };
+ var add2mul3add1 = async.seq(add2, mul3, add1);
+ add2mul3add1(3, function (err, result) {
+ if (err) {
+ return test.done(err);
+ }
+ test.equal(result, 16);
+ test.done();
+ });
+};
+
+exports['seq error'] = function (test) {
+ test.expect(3);
+ var testerr = new Error('test');
+
+ var add2 = function (n, cb) {
+ test.equal(n, 3);
+ setTimeout(function () {
+ cb(null, n + 2);
+ }, 50);
+ };
+ var mul3 = function (n, cb) {
+ test.equal(n, 5);
+ setTimeout(function () {
+ cb(testerr);
+ }, 15);
+ };
+ var add1 = function (n, cb) {
+ test.ok(false, 'add1 should not get called');
+ setTimeout(function () {
+ cb(null, n + 1);
+ }, 100);
+ };
+ var add2mul3add1 = async.seq(add2, mul3, add1);
+ add2mul3add1(3, function (err, result) {
+ test.equal(err, testerr);
+ test.done();
+ });
+};
+
+exports['seq binding'] = function (test) {
+ test.expect(4);
+ var testerr = new Error('test');
+ var testcontext = {name: 'foo'};
+
+ var add2 = function (n, cb) {
+ test.equal(this, testcontext);
+ setTimeout(function () {
+ cb(null, n + 2);
+ }, 50);
+ };
+ var mul3 = function (n, cb) {
+ test.equal(this, testcontext);
+ setTimeout(function () {
+ cb(null, n * 3);
+ }, 15);
+ };
+ var add2mul3 = async.seq(add2, mul3);
+ add2mul3.call(testcontext, 3, function (err, result) {
+ if (err) {
+ return test.done(err);
+ }
+ test.equal(this, testcontext);
+ test.equal(result, 15);
+ test.done();
+ });
+};
+
exports['auto'] = function(test){
var callOrder = [];
var testdata = [{test: 'test'}];