半夜睡觉,睡了一半被惊醒了,睡不着之际,起床更新博客。
抛出一个问题 setTimeout 属于eventloop 哪个任务。
我屮艸芔茻,平时我是写下调用下,我屮艸芔茻, 这个问题就像手写一个new 一样,平时都是用,谁管它的位置啊 实现啊。
那么不好意思,一个事实就是不太算高级前端的问题,初级往上一点,不到中级这么一个阶段人家 肯定会问你这个问题。。。哈哈蓝瘦香菇是吧。 这篇 文章就再次总结下 eventloop
上一片文章 就提到了JS 在浏览器是单线程机制这个问题。
这里还得引用阮一峰老师的话,JS 是单线程与它的用途有关,作为浏览器脚本语言,js 主要作用是用户进行互动,以及操作DOM。这决定了它只能是单线程。否则会带来很复杂的同步问题。比如javascript 有两个线程,一个线程在某个DOM节点上添加内容,另一个是删除这个节点,这时浏览器应该以哪个线程为准。
好进入主题
任务队列
单线程就意味着,所有任务需要排队,前一个任务结束。才会执行后一个任务。如果前一个任务很长,后一个任务就不得不一直进行等待着。
如果排队呢是因为计算量大,CPU忙活不过来,也就算了,但是很多的时候CPU 是闲着的,因为IO设备( 输入输出设备 )很慢(比如AJAX 操作从网络读取数据),不得不等着结果出来再往下执行。
JS 的语言设计者意识到,这时主线程完全可以不管IO 设备,挂起处于等待中的任务,先运行后面的任务,等IO 设备有了返回结果,在回过头,把挂起的任务执行下去。
synchronous [ˈsɪŋkrənəs]
asynchronous [eɪˈsɪŋkrənəs]
于是任务被分成了俩种,一种是同步任务( synchronous )另外一种是异步任务(asynchronous),同步任务( synchronous )是指在主线程上排队的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务是指的是,不进入主线程、从而进入 "任务队列"(task queue)的任务,只有“任务队列”通知主线程,某个异步任务可以执行了,该任务会进入主线程执行。
具体来书,异步执行的运行机制如下。(同步任务也是如此,因为它可以被视为没有异步任务的异步执行)
所有的同步任务都在主线程上执行,形成一个执行栈 ( execution context stack )
主线程之外,还存在一个'任务队列’。只要异步任务有了运行结果,就在'任务队列'之中防置一个事件。
一旦'执行栈'中的所有同步任务执行完毕,系统就会读取‘任务队列’,看看里面有哪些事件。哪些对应的异步任务,于是结束等待状态,进入执行栈,开始执行
主线程不断重复上面3个步骤
上图

三 事件与回调函数
'任务队列'是一个事件队列,也可以理解为(消息队列),IO 设备完成一项任务,就在任务队列里面添加一个事件。,表示相关异步任务可以进入执行栈了。主线程读取'任务队列',就是读取里面有哪些事件。
'任务队列'中的事件,除了IO设备的事件以外,还包括用户产生的一些事件(比如鼠标点击、页面滚动等等). 只要指定过回调函数。这些事件发生就会进入'任务队列',等待主线程读取
所谓'回调函数'(callback),就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主进程开始执行异步任务。就执行对应的回调函数。
'任务队列' 是一个先进先出的数据结构,排在前面的事件,优先被进程读取。主线程的读取基本上是自动的,只要执行栈一清空,‘任务队列’ 上第一位的事件就自动进入主进程。定时器这个单独讲。某些事件只要到了规定时间,才能返回主线程。
讲了这么多回到我们的问题 setTimeout 属于eventloop 哪个任务
说着问题之前 还是上图吧,

思考下浏览器器中输出什么 什么,为什么会这么输出。
可以肯定的是setTimeout 一定是输出在最后的。

原因就是 一个任务promise 跑起来,它的这个回调会直接进入微任务队列, 几个同步任务的console.log() 的任务。都跑完之后。setTimeout的回调状态是挂起。在任务队列里,然而promse 的微任务 确是要立即执行的。

有兴趣的人 可以去试试,其意思就是 Tasks 是算一个新任务的 而 setTimeout 恰巧在其中。 Microtasks 微任务队列 也就是 Promsise then 的方法, 微任务 有返回即执行, 从图上来看 Microtasks 要比 任务的优先级别要高,然而 这是在谷歌浏览器的基本使用方法,在其他浏览器又不尽其然。 在翻看了网上其他文章也就大同小异。
其他不尽奇然的浏览器会进行突变,突变任务 这个坑给埋着吧,想知道的去看大佬原文。

这个谷歌大佬的原文。
https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
还有参考
http://troland.github.io/2017/12/21/%E4%BB%BB%E5%8A%A1%EF%BC%8C%E5%BE%AE%E4%BB%BB%E5%8A%A1%EF%BC%8C%E9%98%9F%E5%88%97%EF%BC%8C%E8%AE%A1%E5%88%92/
阮老师的
http://www.ruanyifeng.com/blog/2014/10/event-loop.html
b站有up 上传过,这是地址。
https://www.bilibili.com/video/av58328816/
文章采用 知识共享署名 4.0 国际许可协议 进行许可,转载时请注明原文链接。