概述
先看个代码,想一下执行结果是什么?
var arr = [1, 2, 3, 4, 5, 6];
for (var i = 0; i < arr.length; i++) {
setTimeout(function () {
console.log(i);
console.log(arr[i]);
}, 2000);
}
预期结果是console 了 1,2,3,4,5,6
但是实际上是
为什么会这样?原因很简单,js代码的运行机制分为微任务和宏任务,先执行微任务,再执行宏任务,setTimeout()函数回调属于异步任务,会出现在宏任务队列中,被压到了任务队列的最后,在这段代码应该是for循环这个同步任务执行完成后才会轮到它,所以for循环在遍历过程中i不断加1,直到i判断失败一次才停止,这时候i为5,也就是说空跑了5次循环。等到了setTimeOut预定的时间后就会执行在for遍历过程中声明的5个setTimeout。所以最终运行后会出现undefind。
正确的解决方案是
1.不用var,使用let来定义变量,let和var的区别就不用多说了,块级作用域,JS中的for循环体比较特殊,每次执行都是一个全新的独立的块作用域,用let声明的变量传入到 for循环体的作用域后,不会发生改变,不受外界的影响。
2.闭包,在闭包函数内部形成了局部作用域,每循环一次,形成一个自己的局部作用域,不受外部变量变化的影响。
晚上写代码的时候,遇到一个需求,我需要在一个for循环中,连续循环发送请求调用ajax接口,以及执行异步函数,如果想要这些异步串行变为同步应该怎么做?
- 回调 callback 嵌套异步操作、再回调的方式
- Promise + then() 层层嵌套
- async和await
我个人认为最优秀的解决方式是async和await,毕竟写法也比较优雅
如果要去将一批数据发送到服务器,只有前一批发送成功(即服务器返回成功的响应),才开始下一批数据的发送,否则终止发送。这就是一个典型的 “for 循环中存在相互依赖的异步操作” 的例子
晚上实战代码
使用await之后,实现了异步变成同步的转化,只有for循环中当次对应的发送请求完成且获取结果,才会继续往下执行。
await几点说明:
- await执行的那一行语句是同步的。
- async函数执行后,总是返回一个promise对象,可以理解为这个函数是一个异步函数(外异)但是当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。
最后
以上就是友好戒指为你收集整理的JavaScript中的for循环—for循环中批量调用接口的全部内容,希望文章能够帮你解决JavaScript中的for循环—for循环中批量调用接口所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复