文章目录
- 基础方法
- arrayEachIndexValue
- baseEachIndexValue
- symbolEachIndexValue
- compact
- timesSync
- 异步遍历
- filter
- filterLimit
- filterSeries
基础方法
arrayEachIndexValue
function arrayEachIndexValue(array, iterator, createCallback) {var value;var index = -1;var size = array.length;if (iterator.length === 3) {while (++index < size) {value = array[index];iterator(value, index, createCallback(index, value));}} else {while (++index < size) {value = array[index];iterator(value, createCallback(index, value));}}
}
baseEachIndexValue
function baseEachIndexValue(object, iterator, createCallback, keys) {var key, value;var index = -1;var size = keys.length;if (iterator.length === 3) {while (++index < size) {key = keys[index];value = object[key];iterator(value, key, createCallback(index, value));}} else {while (++index < size) {value = object[keys[index]];iterator(value, createCallback(index, value));}}
}
symbolEachIndexValue
function symbolEachIndexValue(collection, iterator, createCallback) {var value, item;var index = 0;var iter = collection[iteratorSymbol]();if (iterator.length === 3) {while ((item = iter.next()).done === false) {value = item.value;iterator(value, index, createCallback(index++, value));}} else {while ((item = iter.next()).done === false) {value = item.value;iterator(value, createCallback(index++, value));}}return index;
}
compact
- 筛选数组中所有true的元素
function compact(array) {var index = -1;var size = array.length;var result = [];while (++index < size) {var value = array[index];if (value) {result[result.length] = value;}}return result;
}
timesSync
function timesSync(n, iterator) {var index = -1;while (++index < n) {iterator(index);}
}
异步遍历
filter
基本使用
// array
var order = [];
var array = [1, 3, 2];
var iterator = function(num, done) {setTimeout(function() {order.push(num);done(null, num % 2);}, num * 10);
};
async.filter(array, iterator, function(err, res) {console.log(res); // [1, 3];console.log(order); // [1, 2, 3]
});
实现
var filter = createFilter(arrayEachIndexValue, baseEachIndexValue, symbolEachIndexValue, true);function createFilter(arrayEach, baseEach, symbolEach, bool) {return function(collection, iterator, callback) {callback = callback || noop;var size, keys, result;var completed = 0;if (isArray(collection)) {size = collection.length;result = Array(size);arrayEach(collection, iterator, createCallback);} else if (!collection) {} else if (iteratorSymbol && collection[iteratorSymbol]) {result = [];size = symbolEach(collection, iterator, createCallback);size && size === completed && callback(null, compact(result));} else if (typeof collection === obj) {keys = nativeKeys(collection);size = keys.length;result = Array(size);baseEach(collection, iterator, createCallback, keys);}if (!size) {return callback(null, []);}function createCallback(index, value) { // 闭包记录索引和元素值return function done(err, res) {if (index === null) {throwError();}if (err) {index = null;callback = once(callback);callback(err);return;}if (!!res === bool) { // 异步回调结果为true时才记录result[index] = value; // 通过闭包index保存异步任务对应位置}index = null;if (++completed === size) { // 会等到所有任务执行完毕后,筛选出true的元素callback(null, compact(result));}};}};
}
filterLimit
- 限制每次执行的异步任务数量
var filterLimit = createFilterLimit(true);function createFilterLimit(bool) {return function(collection, limit, iterator, callback) {callback = callback || noop;var size, index, key, value, keys, iter, item, iterate, result;var sync = false;var started = 0;var completed = 0;if (isArray(collection)) {size = collection.length;iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;} else if (!collection) {} else if (iteratorSymbol && collection[iteratorSymbol]) {size = Infinity; // 注意迭代器类型不知道size有多少个result = [];iter = collection[iteratorSymbol]();iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;} else if (typeof collection === obj) {keys = nativeKeys(collection);size = keys.length;iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;}if (!size || isNaN(limit) || limit < 1) {return callback(null, []);}result = result || Array(size);timesSync(limit > size ? size : limit, iterate);function arrayIterator() {index = started++;if (index < size) {value = collection[index];iterator(value, createCallback(value, index));}}function arrayIteratorWithIndex() {index = started++;if (index < size) {value = collection[index];iterator(value, index, createCallback(value, index));}}function symbolIterator() {item = iter.next();if (item.done === false) {value = item.value;iterator(value, createCallback(value, started++));} else if (completed === started && iterator !== noop) { // completed === started 表明已迭代完毕,createCallback对于迭代器类型只负责++completediterator = noop;callback(null, compact(result));}}function symbolIteratorWithKey() {item = iter.next();if (item.done === false) {value = item.value;iterator(value, started, createCallback(value, started++));} else if (completed === started && iterator !== noop) {iterator = noop;callback(null, compact(result));}}function objectIterator() {index = started++;if (index < size) {value = collection[keys[index]];iterator(value, createCallback(value, index));}}function objectIteratorWithKey() {index = started++;if (index < size) {key = keys[index];value = collection[key];iterator(value, key, createCallback(value, index));}}function createCallback(value, index) {return function(err, res) {if (index === null) {throwError();}if (err) {index = null;iterate = noop;callback = once(callback);callback(err);return;}if (!!res === bool) {result[index] = value;}index = null;if (++completed === size) {callback = onlyOnce(callback);callback(null, compact(result));} else if (sync) {nextTick(iterate);} else {sync = true;iterate();}sync = false;};}};
}
filterSeries
- 串行执行,在上一个任务done之后再执行下一个任务
var filterSeries = createFilterSeries(true);function createFilterSeries(bool) {return function(collection, iterator, callback) {callback = onlyOnce(callback || noop);var size, key, value, keys, iter, item, iterate;var sync = false;var completed = 0;var result = [];if (isArray(collection)) {size = collection.length;iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;} else if (!collection) {} else if (iteratorSymbol && collection[iteratorSymbol]) {size = Infinity;iter = collection[iteratorSymbol]();iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;} else if (typeof collection === obj) {keys = nativeKeys(collection);size = keys.length;iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;}if (!size) {return callback(null, []);}iterate();function arrayIterator() {value = collection[completed];iterator(value, done);}function arrayIteratorWithIndex() {value = collection[completed];iterator(value, completed, done);}function symbolIterator() {item = iter.next();value = item.value;item.done ? callback(null, result) : iterator(value, done);}function symbolIteratorWithKey() {item = iter.next();value = item.value;item.done ? callback(null, result) : iterator(value, completed, done);}function objectIterator() {key = keys[completed];value = collection[key];iterator(value, done);}function objectIteratorWithKey() {key = keys[completed];value = collection[key];iterator(value, key, done);}function done(err, res) {if (err) {callback(err);return;}if (!!res === bool) {result[result.length] = value;}if (++completed === size) {iterate = throwError;callback(null, result);} else if (sync) {nextTick(iterate);} else {sync = true;iterate();}sync = false;}};
}