Skip to content

Commit 1717027

Browse files
committed
Add async.tryEach, Fixes caolan#687
1 parent 8903d46 commit 1717027

File tree

3 files changed

+152
-0
lines changed

3 files changed

+152
-0
lines changed

lib/index.js

+3
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ import times from './times';
8989
import timesLimit from './timesLimit';
9090
import timesSeries from './timesSeries';
9191
import transform from './transform';
92+
import tryEach from './tryEach';
9293
import unmemoize from './unmemoize';
9394
import until from './until';
9495
import waterfall from './waterfall';
@@ -163,6 +164,7 @@ export default {
163164
timesLimit: timesLimit,
164165
timesSeries: timesSeries,
165166
transform: transform,
167+
tryEach: tryEach,
166168
unmemoize: unmemoize,
167169
until: until,
168170
waterfall: waterfall,
@@ -255,6 +257,7 @@ export {
255257
timesLimit as timesLimit,
256258
timesSeries as timesSeries,
257259
transform as transform,
260+
tryEach as tryEach,
258261
unmemoize as unmemoize,
259262
until as until,
260263
waterfall as waterfall,

lib/tryEach.js

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import noop from 'lodash/noop';
2+
import eachSeries from './eachSeries';
3+
import rest from './internal/rest';
4+
5+
/**
6+
* It runs each task in series but stops whenever any of the functions were
7+
* successful. If one of the tasks were successful, the `callback` will be
8+
* passed the result of the successful task. If all tasks fail, the callback
9+
* will be passed the error and result (if any) of the final attempt.
10+
*
11+
* @name tryEach
12+
* @static
13+
* @memberOf module:ControlFlow
14+
* @method
15+
* @category Control Flow
16+
* @name series
17+
* @static
18+
* @memberOf module:ControlFlow
19+
* @method
20+
* @category Control Flow
21+
* @param {Array|Iterable|Object} tasks - A collection containing functions to
22+
* run, each function is passed a `callback(err, result)` it must call on
23+
* completion with an error `err` (which can be `null`) and an optional `result`
24+
* value.
25+
* @param {Function} [callback] - An optional callback which is called when one
26+
* of the tasks has succeeded, or all have failed. It receives the `err` and
27+
* `result` arguments of the last attempt at completing the `task`. Invoked with
28+
* (err, results).
29+
* @example
30+
* async.try([
31+
* function getDataFromFirstWebsite(callback) {
32+
* // Try getting the data from the first website
33+
* callback(err, data);
34+
* },
35+
* function getDataFromSecondWebsite(callback) {
36+
* // First website failed,
37+
* // Try getting the data from the backup website
38+
* callback(err, data);
39+
* }
40+
* ],
41+
* // optional callback
42+
* function(err, results) {
43+
* Now do something with the data.
44+
* });
45+
*
46+
*/
47+
export default function tryEach(tasks, callback) {
48+
var error = null;
49+
var result;
50+
callback = callback || noop;
51+
eachSeries(tasks, function(task, callback) {
52+
task(rest(function (err, args) {
53+
if (args.length <= 1) {
54+
args = args[0];
55+
}
56+
error = err;
57+
result = args;
58+
callback(args);
59+
}));
60+
}, function () {
61+
callback(error, result);
62+
});
63+
}

mocha_test/tryEach.js

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
var async = require('../lib');
2+
var expect = require('chai').expect;
3+
var assert = require('assert');
4+
5+
describe('try', function () {
6+
it('no callback', function () {
7+
async.tryEach([]);
8+
});
9+
it('empty', function (done) {
10+
async.tryEach([], function (err, results) {
11+
expect(err).to.equal(null);
12+
expect(results).to.eql(undefined);
13+
done();
14+
});
15+
});
16+
it('one task, multiple results', function (done) {
17+
var RESULTS = ['something', 'something2'];
18+
async.tryEach([
19+
function (callback) {
20+
callback(null, RESULTS[0], RESULTS[1]);
21+
}
22+
], function (err, results) {
23+
expect(err).to.equal(null);
24+
expect(results).to.eql(RESULTS);
25+
done();
26+
});
27+
});
28+
it('one task', function (done) {
29+
var RESULT = 'something';
30+
async.tryEach([
31+
function (callback) {
32+
callback(null, RESULT);
33+
}
34+
], function (err, results) {
35+
expect(err).to.equal(null);
36+
expect(results).to.eql(RESULT);
37+
done();
38+
});
39+
});
40+
it('two tasks, one failing', function (done) {
41+
var RESULT = 'something';
42+
async.tryEach([
43+
function (callback) {
44+
callback(new Error('Failure'));
45+
},
46+
function (callback) {
47+
callback(null, RESULT);
48+
}
49+
], function (err, results) {
50+
expect(err).to.equal(null);
51+
expect(results).to.eql(RESULT);
52+
done();
53+
});
54+
});
55+
it('two tasks, both failing', function (done) {
56+
var ERROR_RESULT = new Error('Failure2');
57+
async.tryEach([
58+
function (callback) {
59+
callback(new Error('Should not stop here'));
60+
},
61+
function (callback) {
62+
callback(ERROR_RESULT);
63+
}
64+
], function (err, results) {
65+
expect(err).to.equal(ERROR_RESULT);
66+
expect(results).to.eql(undefined);
67+
done();
68+
});
69+
});
70+
it('two tasks, non failing', function (done) {
71+
var RESULT = 'something';
72+
async.tryEach([
73+
function (callback) {
74+
callback(null, RESULT);
75+
},
76+
function () {
77+
assert.fail('Should not been called');
78+
},
79+
], function (err, results) {
80+
expect(err).to.equal(null);
81+
expect(results).to.eql(RESULT);
82+
done();
83+
});
84+
});
85+
});
86+

0 commit comments

Comments
 (0)