异步控制流程 遍历篇each
创始人
2024-06-03 08:36:48
0

文章目录

  • 基础方法
    • onlyOnce 只执行一次,第二次报错
    • once 只执行一次,第二次无效
    • iteratorSymbol 判断是否具有迭代器并返回迭代器
    • arrayEach 普通数组遍历
    • baseEach 对象类型遍历
    • symbolEach 具有迭代器类型遍历
  • 异步遍历
    • each
    • eachLimit
    • eachSeries

异步控制流程的目的:

  • 对异步操作提供类似同步遍历的操作
  • 本文的Promise兼容均为在原本只支持node回调的方式下修改

基础方法

onlyOnce 只执行一次,第二次报错

  • 只执行一次,因为第二次func变成了抛出错误
function onlyOnce(func) {return function(err, res) {var fn = func;func = throwError;fn(err, res);};
}

once 只执行一次,第二次无效

  • 只执行一次,因为第二次func变成了空函数
 function once(func) {return function(err, res) {var fn = func;func = noop;fn(err, res);};}

iteratorSymbol 判断是否具有迭代器并返回迭代器

var iteratorSymbol = typeof Symbol === func && Symbol.iterator;

arrayEach 普通数组遍历

- iterator:每次遍历的回调- callback:内部有个计数器,执行遍历完成后的回调function arrayEach(array, iterator, callback) {var index = -1;var size = array.length;// 三个参数情况if (iterator.length === 3) {while (++index < size) {// 传入value、key、手动计数最后遍历完成回调(只有第一次执行有效)iterator(array[index], index, onlyOnce(callback));}} else { // 两个参数情况while (++index < size) {iterator(array[index], onlyOnce(callback));}}
}

baseEach 对象类型遍历

function baseEach(object, iterator, callback, keys) {var key;var index = -1;var size = keys.length;// 三个参数情况if (iterator.length === 3) {while (++index < size) {key = keys[index];iterator(object[key], key, onlyOnce(callback));}} else { // 两个参数情况while (++index < size) {iterator(object[keys[index]], onlyOnce(callback));}}
}

symbolEach 具有迭代器类型遍历

  function symbolEach(collection, iterator, callback) {var iter = collection[iteratorSymbol]();var index = 0;var item;// 三个参数情况if (iterator.length === 3) {while ((item = iter.next()).done === false) {iterator(item.value, index++, onlyOnce(callback));}} else {// 两个参数情况while ((item = iter.next()).done === false) {index++;iterator(item.value, onlyOnce(callback));}}return index;}

异步遍历

each

  • 实现 forEach 效果
  • 原理:每次回调中执行计数器,判断计数完毕时,执行结束回调
exports.each=createEach(arrayEach, baseEach, symbolEach)function createEach(arrayEach, baseEach, symbolEach) {return function each(collection, iterator, callback) {let promise=new Promise((resolve,reject)=>{callback = once(callback || noop);var size, keys;var completed = 0;if (isArray(collection)) {size = collection.length;arrayEach(collection, iterator, done);} else if (iteratorSymbol && collection[iteratorSymbol]) {size = symbolEach(collection, iterator, done);size && size === completed && callback(null);} else if (typeof collection === obj) {// Object.keyskeys = nativeKeys(collection);size = keys.length;baseEach(collection, iterator, done, keys);}if (!size) {callback(null);reject('value should be an object');}function done(err, bool) {if (err) {callback = once(callback);callback(err);reject(err);} else if (++completed === size) {callback(null);resolve('null')} else if (bool === false) {callback = once(callback);callback(null);reject('cancel');}}})return promise.then((res)=>res).catch(err=> Promise.reject(err))};}

基本使用:

const array = { a: 1, b: 3, c: 2 };;
const iterator = function(key, value,done) {setTimeout(function() {done()// done() done只有第一次执行有效// done(err)、done(null,false) 结束遍历并执行最终回调}, key * 1000);
};// 回调方式
nac.each(array, iterator, function(err) {console.log('done')
});// Promise方式
async function neo(){try {let res=await nac.each(array, iterator);console.log('success',res);    } catch (error) {console.log('error',error)}}

eachLimit

  • 不保证回调顺序,限制每一次异步请求的次数
  • 原理:只需要限制第一次发起请求的次数,然后在每一次请求回调中调用后续请求,即可实现每一次请求数量小于n

基本使用

var array = [1, 5, 3, 4, 2];
var iterator = function(value,key,done) {setTimeout(function() {done(null, num % 2);}, num * 10);
};
async.everyLimit(array, 2, iterator, function(err, res) {console.log(res); // falseconsole.log(order); // [1, 3, 5, 2]
});
function eachLimit(collection, limit, iterator, callback) {callback = callback || noop;var size, index, key, keys, iter, item, iterate;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;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;} else {return callback(null);}if (!size || isNaN(limit) || limit < 1) {return callback(null);}timesSync(limit > size ? size : limit, iterate);// 数组的遍历器,根据索引进行遍历function arrayIterator() {if (started < size) {iterator(collection[started++], done);}}function arrayIteratorWithIndex() {index = started++;if (index < size) {iterator(collection[index], index, done);}}// symbol类型的遍历function symbolIterator() {item = iter.next();if (item.done === false) {started++;iterator(item.value, done);} else if (completed === started && iterator !== noop) { // 当遍历方法同步且多done的时候可能出现,可以忽略这种ifiterator = noop;callback(null);}}function symbolIteratorWithKey() {item = iter.next();if (item.done === false) {iterator(item.value, started++, done);} else if (completed === started && iterator !== noop) {iterator = noop;callback(null);}}// 对象的遍历function objectIterator() {if (started < size) {iterator(collection[keys[started++]], done);}}function objectIteratorWithKey() {index = started++;if (index < size) {key = keys[index];iterator(collection[key], key, done);}}function done(err, bool) {if (err || bool === false) {iterate = noop;callback = once(callback);callback(err);} else if (++completed === size) {iterator = noop;iterate = throwError;callback = onlyOnce(callback);callback(null);} else if (sync) {// procces.nextTick、setImmediate、setTimeoutnextTick(iterate);} else {sync = true;iterate();}sync = false;}
}

eachSeries

  • 保证异步串行
  • 原理:在每一次异步回调后再调用后续异步方法

基本使用:

var order = [];
var array = [1, 3, 2];
var iterator = function(value, done) {setTimeout(function() {order.push(num);done();}, num * 10);
};
async.eachSeries(array, iterator, function(err, res) {console.log(res); // undefinedconsole.log(order); // [1, 3, 2]
});
function eachSeries(collection, iterator, callback) {callback = onlyOnce(callback || noop);var size, key, keys, iter, item, iterate;var sync = false;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;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() {iterator(collection[completed], done);}function arrayIteratorWithIndex() {iterator(collection[completed], completed, done);}function symbolIterator() {item = iter.next();item.done ? callback(null) : iterator(item.value, done);}function symbolIteratorWithKey() {item = iter.next();item.done ? callback(null) : iterator(item.value, completed, done);}function objectIterator() {iterator(collection[keys[completed]], done);}function objectIteratorWithKey() {key = keys[completed];iterator(collection[key], key, done);}// 在异步回调中调用后续方法function done(err, bool) {if (err) {callback(err);} else if (++completed === size || bool === false) {iterate = throwError;callback(null);} else if (sync) {nextTick(iterate);} else {sync = true;iterate();}sync = false;}
}

相关内容

热门资讯

安卓系统上位机编写,基于安卓系... 你有没有想过,手机里的安卓系统其实是个大宝藏呢?它不仅能让你的生活变得丰富多彩,还能让你成为编程小达...
华为平板安卓7.1系统,探索性... 你有没有发现,最近华为平板的新款机型简直让人眼前一亮?没错,我要跟你聊聊的就是这款搭载了安卓7.1系...
鸿蒙系统安卓怎么升级,轻松实现... 你有没有发现,最近你的华为手机好像有点不一样了?没错,那就是鸿蒙系统升级的魅力!今天,就让我来带你一...
安卓引导系统的软件,架构、功能... 你有没有发现,每次打开安卓手机,那熟悉的引导系统就像一位热情的导游,带你一步步走进这个五彩斑斓的数字...
谷歌做的安卓系统,安卓系统的创... 亲爱的读者,你是否曾好奇过,那个几乎无处不在的安卓系统,究竟是由谁打造的呢?没错,就是那个改变世界的...
安卓系统总提示更新系统,体验流... 手机又闹腾了!安卓系统总提示更新系统,你是不是也和我一样,每次看到这个提示就有点头疼呢?别急,今天就...
aos是安卓系统么?,安卓系统... 你有没有想过,手机里的那个神秘的aos系统,它是不是安卓家族的一员呢?今天,就让我带你一探究竟,揭开...
诺基亚8刷安卓系统,解锁无限可... 你手中的诺基亚8是不是已经有点儿落伍了呢?别急,今天就来给你支个招,让你的老伙计焕发新生,变身安卓小...
安卓系统能不能,可以。 你有没有想过,安卓系统到底能不能?这个问题,就像是在问一个老朋友,他是不是真的懂你。安卓系统,这个陪...
安卓系统恢复误删视频,轻松找回... 手机里的视频突然不见了,是不是你也遇到了这样的尴尬情况?别急,今天就来教你如何用安卓系统恢复误删的视...
华为安卓系统的siri,华为安... 你知道吗?华为最近在安卓系统上搞了个大动作,那就是推出了自己的Siri——华为助手。这可真是让人眼前...
wp模拟安卓系统界面,畅游虚拟... 你有没有想过,在电脑上也能体验到安卓系统的流畅与便捷呢?没错,这就是今天我要跟你分享的神奇小玩意——...
安卓系统的开发团队,谷歌开发团... 你知道吗?在科技的世界里,有一个团队可是默默无闻地创造了无数奇迹,他们就是安卓系统的开发团队。这个团...
俄语流利说安卓系统,轻松掌握俄... 你有没有想过,学习一门新语言竟然可以变得如此轻松有趣?没错,我要给你安利一款神器——俄语流利说安卓系...
安卓P系统原装铃声,唤醒科技之... 你有没有发现,手机里的那些原装铃声,有时候比我们自己的手机铃声还要动听呢?尤其是安卓P系统的原装铃声...
稳定无广告安卓系统,探索稳定无... 你有没有想过,手机系统就像是我们生活的环境,有时候干净整洁,有时候却满是杂乱无章的广告?今天,我要给...
安卓系统隔离运行app,技术革... 你知道吗?在智能手机的世界里,安卓系统可是个超级明星呢!它不仅功能强大,而且兼容性极好,几乎所有的手...
佳博3120安卓系统,引领移动... 你有没有听说过佳博3120安卓系统?这款设备最近可是火得一塌糊涂呢!想象一台集成了安卓系统的打印机,...
安卓系统放音乐全屏,沉浸式听觉... 你有没有发现,用安卓手机放音乐的时候,有时候屏幕会自动全屏显示,这可真是挺有趣的。你知道吗?这个小小...
安卓子系统是win,基于Win... 你知道吗?在科技的世界里,总是充满了惊喜和未知。今天,我要给你揭秘一个你可能没听说过的秘密:安卓子系...