因为浏览器有个定时器(timer)模块,定时器到了执行时间才会把异步任务放到异步队列。
for循环体执行的过程中并没有把setTimeout放到异步队列中,只是交给定时器模块了。4个循环体执行速度非常快(不到1毫秒)。定时器到了设置的时间才会把setTimeout语句放到异步队列中。
即使setTimeout设置的执行时间为0毫秒,也按4毫秒算。
这就解释了上题为什么会连续输出四个4的原因。
HTML5 标准规定了setTimeout()的第二个参数的最小值,即最短间隔,不得低于4毫秒。如果低于这个值,就会自动增加。在此之前,老版本的浏览器都将最短间隔设为10毫秒。
利用闭包实现 setTimeout 间歇调用
for (let i = 0; i < 4; i++) { (function (j) { setTimeout(function () { console.log(j); }, 1000 * i) })(i); }
执行后,会隔1s输出一个值,分别是:0 1 2 3
此方法巧妙利用IIFE声明即执行的函数表达式来解决闭包造成的问题。
将var改为let,使用了ES6语法。
这里也可以用setInterval()方法来实现间歇调用。
利用JS中基本类型的参数传递是按值传递的特征实现
var output = function (i) { setTimeout(function () { console.log(i); }, 1000 * i) } for (let i = 0; i < 4; i++) { output(i); }
执行后,会隔1s输出一个值,分别是:0 1 2 3
实现原理:传过去的i值被复制了。
基于Promise的解决方案
const tasks = []; const output = (i) => new Promise((resolve) => { setTimeout(() => { console.log(i); resolve(); }, 1000 * i); }); //生成全部的异步操作 for (var i = 0; i < 5; i++) { tasks.push(output(i)); } //同步操作完成后,输出最后的i Promise.all(tasks).then(() => { setTimeout(() => { console.log(i); }, 1000) })
执行后,会隔1s输出一个值,分别是:0 1 2 3 4 5
优点:提高了代码的可读性。
注意:如果没有处理Promise的reject,会导致错误被丢进黑洞。
使用ES7中的async await特性的解决方案(推荐)
const sleep = (timeountMS) => new Promise((resolve) => { setTimeout(resolve, timeountMS); }); (async () => { //声明即执行的async for (var i = 0; i < 5; i++) { await sleep(1000); console.log(i); } await sleep(1000); console.log(i); })();
执行后,会隔1s输出一个值,分别是:0 1 2 3 4 5
六、事件循环 Event Loop
主线程从任务队列中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop。
有时候 setTimeout明明写的延时3秒,实际却5,6秒才执行函数,这又是因为什么?
答:setTimeout 并不能保证执行的时间,是否及时执行取决于 JavaScript 线程是拥挤还是空闲。
浏览器的JS引擎遇到setTimeout,拿走之后不会立即放入异步队列,同步任务执行之后,timer模块会到设置时间之后放到异步队列中。js引擎发现同步队列中没有要执行的东西了,即运行栈空了就从异步队列中读取,然后放到运行栈中执行。所以setTimeout可能会多了等待线程的时间。
这时setTimeout函数体就变成了运行栈中的执行任务,运行栈空了,再监听异步队列中有没有要执行的任务,如果有就继续执行,如此循环,就叫Event Loop。
七、总结
JavaScript通过事件循环和浏览器各线程协调共同实现异步。同步可以保证顺序一致,但是容易导致阻塞;异步可以解决阻塞问题,但是会改变顺序性。
知识点梳理:
理解JS的单线程的概念:一段时间内做一件事
理解任务队列:同步任务、异步任务
理解 Event Loop
理解哪些语句会放入异步任务队列
理解语句放入异步任务队列的时机
最后,希望大家阅后有所收获。🤠
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。
您可能感兴趣的文章: