Skip to content

Commit cca5b49

Browse files
committed
fix: ensure sync errors are thrown, and don't callback twice
1 parent 40f5911 commit cca5b49

File tree

2 files changed

+51
-16
lines changed

2 files changed

+51
-16
lines changed

lib/core/utils.js

+15-16
Original file line numberDiff line numberDiff line change
@@ -131,30 +131,29 @@ function isPromiseLike(maybePromise) {
131131
* @param {function} callback The callback called after every item has been iterated
132132
*/
133133
function eachAsync(arr, eachFn, callback) {
134-
if (arr.length === 0) {
135-
callback(null);
134+
arr = arr || [];
135+
136+
let idx = 0;
137+
let awaiting = 0;
138+
for (idx = 0; idx < arr.length; ++idx) {
139+
awaiting++;
140+
eachFn(arr[idx], eachCallback);
141+
}
142+
143+
if (awaiting === 0) {
144+
callback();
136145
return;
137146
}
138147

139-
const length = arr.length;
140-
let completed = 0;
141148
function eachCallback(err) {
149+
awaiting--;
142150
if (err) {
143-
callback(err, null);
151+
callback(err);
144152
return;
145153
}
146154

147-
if (++completed === length) {
148-
callback(null);
149-
}
150-
}
151-
152-
for (let idx = 0; idx < length; ++idx) {
153-
try {
154-
eachFn(arr[idx], eachCallback);
155-
} catch (err) {
156-
callback(err);
157-
return;
155+
if (idx === arr.length && awaiting <= 0) {
156+
callback();
158157
}
159158
}
160159
}

test/unit/utils.test.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict';
2+
const eachAsync = require('../../lib/core/utils').eachAsync;
3+
const expect = require('chai').expect;
4+
5+
describe('utils', function() {
6+
describe('eachAsync', function() {
7+
it('should callback with an error', function(done) {
8+
eachAsync(
9+
[{ error: false }, { error: true }],
10+
(item, cb) => {
11+
cb(item.error ? new Error('error requested') : null);
12+
},
13+
err => {
14+
expect(err).to.exist;
15+
done();
16+
}
17+
);
18+
});
19+
20+
it('should propagate a synchronously thrown error', function(done) {
21+
expect(() =>
22+
eachAsync(
23+
[{}],
24+
() => {
25+
throw new Error('something wicked');
26+
},
27+
err => {
28+
expect(err).to.not.exist;
29+
done(err);
30+
}
31+
)
32+
).to.throw(/something wicked/);
33+
done();
34+
});
35+
});
36+
});

0 commit comments

Comments
 (0)