for循环里的异步操作如何处理
首先来看一个比较简单的问题,我们想实现的就是每隔1s输出0-4的值,就是这么简单,看下错误写法
:
function test() { for (var i = 0; i < 5; ++i) { setTimeout(function() { console.log("index is :", i); }, 1000); }}test();
以上代码会如何输出?输出如下
index is : 5index is : 5index is : 5index is : 5index is : 5
而且该操作几乎是在同一时间完成,setTimeout定时根本就没有起作用,这是因为:单线程的js在操作时,对于这种异步操作,会先进行一次“保存”,即把异步操作放到堆栈中,等前面的程序执行完,堆栈中的异步操作就会执行。等到整个for循环执行结束后,此时i的值已经变成5,因为setTimeout是写在for循环中的,相当于存在5次定时调用,这5次调用均是在for循环结束后进行的,所以自然而然输出都是5,正确的实现有几种,一般情况下,如下:
递归
box6(); function box7(param) { if (param < 5) { console.log("index is :", param); setTimeout(function() { box7(param + 1); }, 1000) }}box7(0);
正确实现每隔1s打印输出如下:
index is : 0index is : 1index is : 2index is : 3index is : 4
使用递归实现的倒计时:
function showTime(count) { console.log("count is : ", count); if (count == 0) { console.log("All is Done!"); } else { count -= 1; setTimeout(function() { showTime(count); }, 1000); }} showTime(20);
自执行函数
function test() { for (var i = 0; i < 5; ++i) { (function(i){ setTimeout(function() { console.log("index is :", i); }, 1000) })(i) }}test();
异步操作使用异步函数包裹起来,i每次执行都不把i作为参赛传到函数中
let 声明i
function test() { for (let i = 0; i < 5; ++i) { setTimeout(function() { console.log("index is :", i); }, 1000) }}test();
async、await实现
var asyncFunc = function(arr, i) { return new Promise(function(resolve, reject) { setTimeout(function() { arr.push(i); console.log("index is : ", i); resolve(); }, 1000); });} var box5 = async function() { var arr = []; for (var i = 0; i < 5; i++) { await asyncFunc(arr, i); } console.log(arr);} box5();
同样实现每隔1s正确地打印输出如下:
index is : 0index is : 1index is : 2index is : 3index is : 4[ 0, 1, 2, 3, 4 ]
使用promise,函数会等待他执行完才会继续执行下一行代码,相当于是同步代码
作者:为光pig
链接:https://www.jianshu.com/p/31ab0ba91371