Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds support for es6 iterators #898

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"sub": true,
"browser": true,
"node": true,
"esnext": true,
"globals": {
"self": true,
"define": true,
Expand Down
74 changes: 42 additions & 32 deletions lib/async.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
return !v;
}


// global on the server, window in the browser
var previous_async;

Expand All @@ -33,6 +34,8 @@
previous_async = root.async;
}

var iteratorSymbol = typeof Symbol == 'function' && Symbol.iterator;

async.noConflict = function () {
root.async = previous_async;
return async;
Expand Down Expand Up @@ -77,12 +80,6 @@
);
}

function _each(coll, iterator) {
return _isArrayLike(coll) ?
_arrayEach(coll, iterator) :
_forEachOf(coll, iterator);
}

function _arrayEach(arr, iterator) {
var index = -1,
length = arr.length;
Expand Down Expand Up @@ -137,22 +134,32 @@
return keys;
};

function _keyIterator(coll) {
function _iterator(coll) {
var i = -1;
var len;
var keys;

if (_isArrayLike(coll)) {
len = coll.length;
return function next() {
i++;
return i < len ? i : null;
return i < len ? [coll[i], i] : null;
};
} else {
}
else if (iteratorSymbol && coll[iteratorSymbol]) {
var iterator = coll[iteratorSymbol]();
return function next() {
var item = iterator.next();
if (item.done) return null;
return _isArray(item.value) ? item.value : [item.value];
};
}
else {
keys = _keys(coll);
len = keys.length;
return function next() {
i++;
return i < len ? keys[i] : null;
return i < len ? [coll[keys[i]], keys[i]] : null;
};
}
}
Expand Down Expand Up @@ -230,23 +237,26 @@
async.eachOf = function (object, iterator, callback) {
callback = _once(callback || noop);
object = object || [];
var size = _isArrayLike(object) ? object.length : _keys(object).length;
var completed = 0;
if (!size) {
return callback(null);

var iter = _iterator(object);
var item, completed = 0;

while ((item = iter()) != null) {
completed += 1;
iterator(item[0], item[1], only_once(done));
}
_each(object, function (value, key) {
iterator(object[key], key, only_once(done));
});

if (completed === 0) callback(null);

function done(err) {
completed--;
if (err) {
callback(err);
}
else {
completed += 1;
if (completed >= size) {
callback(null);
}
// Check key is null in case iterator isn't exhausted
// and done resolved synchronously.
else if (item === null && completed <= 0) {
callback(null);
}
}
};
Expand All @@ -255,20 +265,20 @@
async.eachOfSeries = function (obj, iterator, callback) {
callback = _once(callback || noop);
obj = obj || [];
var nextKey = _keyIterator(obj);
var key = nextKey();
var iter = _iterator(obj);
var item = iter();
function iterate() {
var sync = true;
if (key === null) {
if (item === null) {
return callback(null);
}
iterator(obj[key], key, only_once(function (err) {
iterator(item[0], item[1], only_once(function (err) {
if (err) {
callback(err);
}
else {
key = nextKey();
if (key === null) {
item = iter();
if (item === null) {
return callback(null);
} else {
if (sync) {
Expand Down Expand Up @@ -296,7 +306,7 @@
return function (obj, iterator, callback) {
callback = _once(callback || noop);
obj = obj || [];
var nextKey = _keyIterator(obj);
var iter = _iterator(obj);
if (limit <= 0) {
return callback(null);
}
Expand All @@ -310,16 +320,16 @@
}

while (running < limit && !errored) {
var key = nextKey();
if (key === null) {
var item = iter();
if (item === null) {
done = true;
if (running <= 0) {
callback(null);
}
return;
}
running += 1;
iterator(obj[key], key, only_once(function (err) {
iterator(item[0], item[1], only_once(function (err) {
running -= 1;
if (err) {
callback(err);
Expand Down
13 changes: 13 additions & 0 deletions test/test-async.js
Original file line number Diff line number Diff line change
Expand Up @@ -1347,6 +1347,19 @@ exports['forEachOf'] = function(test){
});
};

exports['forEachOf - instant resolver'] = function(test){
test.expect(1);
var args = [];
async.forEachOf({ a: 1, b: 2 }, function(x, k, cb) {
args.push(k, x);
cb();
}, function(){
// ensures done callback isn't called before all items iterated
test.same(args, ["a", 1, "b", 2]);
test.done();
});
};

exports['forEachOf empty object'] = function(test){
test.expect(1);
async.forEachOf({}, function(value, key, callback){
Expand Down