昼猫笔记 JavaScript -- 异步执行 | 定时器真的定时执行?

时间:2024-01-22 10:45:41

 

本篇主要内容:异步、定时器引发的思考

预计阅读时间:8分钟


了解

我们都知道在js中定时器有两种  setInterval()  、 setTimeout()  
setInterval() :按照指定的周期(以毫秒计)来调用函数或计算表达式。方法会不停地调用函数,直到  clearInterval()  被调用或窗口被关闭。 
setTimeout() :在指定的毫秒数后调用函数或计算表达式。 
那么问题来了,定时器真的是定时执行的吗? 刚开始我认为定时器肯定是定时执行的啊,要不然怎么会叫做定时器呢,后来我感觉我好像错了,所以今天就来说说这个问题 定时器真的是定时执行的吗


测试

 

1 var start = Date.now()
2 console.log(\'启动定时器前...\')
3 setTimeout(function () {
4    console.log(\'定时器执行了: \', Date.now()-start)
5 }, 100)
6 console.log(\'启动定时器后...\');

 

 

 

 

我们会发现定时器执行了101ms, 一般会延迟一丁点(可以接受),说白了就是准确的,如果说300ms之后执行呢?

var start = Date.now()
console.log(\'启动定时器前...\')
setTimeout(function () {
   console.log(\'定时器执行了: \', Date.now()-start)
}, 100)
console.log(\'启动定时器后...\');
for (var i = 0; i < 1000000000; i++) {

}


如果像上边这种情况,本来是200ms,但是现在变成了1941ms,那还合适吗? 
也就是说我们的定时器真的能保证定时吗? 
答案是不能,也可能延迟执行,是在原有设定的时间上又有延迟,加入本来是200ms, 那么现在是1941ms,所以说定时器并不能真正保证定时执行

注意:定时器的回调函数是在主线程执行,无论是非回调函数还是回调函数都是在主线程执行

 


JS执行方式

这时候就说到了一个概念 --- js是单线程执行的 
那如何证明js执行是单线程的呢?尤其是一些回调函数中,我们把握不住是主线程执行还是分线程执行的,所以我们现在就验证下js是单线程执行的

setTimeout(function () {
   console.log(\'timeout 2\')
}, 2000)

setTimeout(function () {
   console.log(\'timeout 1\')
}, 1000)
function fn () {
   console.log(\'fn()\');
}
fn()
console.log(\'alert之前\')
alert(\'提示...\')
console.log(\'alert之后\')


执行流程:fn() alert之前 弹窗 


当我点击确认后,  timeout 2  和  timeout 1  是立即执行还是过一会执行 


alert之后 timeout 1 timeout 2 


我们发现是过一会执行,所以说 
alert() 的作用是暂停当前主线程,同时暂停计时。 点击确认后,回复程序执行和计时

小结 
如何证明js执行是单线程的? 
setTimeout()  的回调函数是在主线程执行的 
定时器回调函数只有在运行栈中的代码全部执行完后才有可能执行

 

setTimeout(function () {
   alert(\'2222222\')
   console.log(\'timeout 2\')
}, 2000)

setTimeout(function () {
   alert(\'1111111\')
   console.log(\'timeout 1\')
}, 1000)
function fn () {

   console.log(\'fn()\');
}
fn()
console.log(\'alert之前\')
alert(\'提示...\')
console.log(\'alert之后\')

 

 

其实呢到现在咱们也不能清楚地看到JS是如何执行的,要说到这个,我们就得说下代码分类,之前也写过代码分类,全局代码和函数局部代码。 


代码分类

这一次呢我们分为初始化代码和回调代码 
回调代码就是回调函数中的代码 

setTimeout  是本文的初始代码 


接下来就是比较重要的一段函数了 

setTimeout(function () {
   console.log(\'timeout 0\')
}, 0)
console.log(\'昼猫\')

 

这一段代码中是谁先执行? 


总结 

JS引擎执行代码的基本流程: 
先执行初始化代码:包含一些特别的代码,例如:设置定时器、绑定事件监听、发送ajax请求 
在后面在某个时刻才会执行回调代码 
回调函数我们平常时候会说是异步执行 
也就是说某些代码(某些东西)必须在所有的初始化代码执行后才有可能得到被执行,这样的代码我们成为异步代码

 

 孔子东游记               公众号:昼猫笔记


文章转载公众号昼猫笔记