A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 柠檬leung不酸 于 2019-1-23 13:45 编辑

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

测试
var start = Date.now()
console.log('启动定时器前...')
setTimeout(function () {
   console.log('定时器执行了: ', Date.now()-start)
}, 100)
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请求
在后面在某个时刻才会执行回调代码
回调函数我们平常时候会说是异步执行
也就是说某些代码(某些东西)必须在所有的初始化代码执行后才有可能得到被执行,这样的代码我们成为异步代码

今天的内容到这结束了,大家好好消化消化,认清JS的执行流程,清楚异步代码执行流程
---------------------
作者:昼猫
来源:CSDN
原文:https://blog.csdn.net/weixin_44176774/article/details/85944710


1 个回复

倒序浏览
一个人一座城0.0 来自手机 中级黑马 2019-1-24 08:33:57
沙发
看一看。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马