本篇主要内容:异步、定时器引发的思考
预计阅读时间: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请求
在后面在某个时刻才会执行回调代码
回调函数我们平常时候会说是异步执行
也就是说某些代码(某些东西)必须在所有的初始化代码执行后才有可能得到被执行,这样的代码我们成为异步代码
孔子东游记 公众号:昼猫笔记
文章转载公众号昼猫笔记