项目中需要让一个含有异步调用的forEach循环顺序执行,由于JavaScript没有Sleep函数,因此指定自己写一个,网上查阅到的资料大多都是使用while(true){}
这样的循环,实践下来效果并不好,会把程序卡死。这里我提供一个使用setInterval的解决办法,可以在JavaScript中实现阻塞功能,先看代码:
var items = [
{
id: 1,
name: 'a'
},
{
id: 2,
name: 'b'
},
{
id: 3
name: 'c'
},
{
id: 4,
name: 'd'
}
];
//首先给items增加几个用于顺序执行,实现阻塞功能的额外属性
items.forEach(function(item) {
item.intervalCount = 0,
item.intervalValue = null,
item.lockProcess = false
});
var i = 0;
(function loopIt(i) {
items[i].lockProcess = true;
//
doSomethingAsync(items[i], i);
/*
* 让循环顺序执行,设置一个timeout:500x20=10秒,如果超时,则继续下一个item
* 否则,等待当前item的doSomethingAsync完成(lockProcess=false)再继续
*/
items[i].intervalValue = setInterval(function () {
items[i].intervalCount += 1;
if (items[i].intervalCount >= 20) {
items[i].lockProcess = false;
}
if (items[i].lockProcess === false) {
clearInterval(items[i].intervalValue);
if(i < items.length - 1) {
loopIt(i+1);
}
}
}, 500);
})(i);
// 需要异步调用完成的工作
function doSomethingAsync(item, index) {
item.lockProcess = false;
// do something async
}
上面的代码都添加了注释,重点是在递归函数loopIt(i)
里面调用了setInterval()
,在setInterval()
里面检查当前项目的执行锁lockProcess
如果执行完成或者超时(为setInterval
设置了一个超时次数20),就销毁执行锁item.lockProcess = false
并退出setInterval
,继续执行下一项。不知道你看明白了吗?如果有任务疑问,欢迎来Bloghome给我提问吧!
参考文章:
Can clearInterval() be called inside setInterval()?
Add a delay after executing each iteration with forEach loop