摘要:中线程运行机制详解对于我们都知道,他是个单线程语言,但是准确来说它是拥有一个执行程序主线程,和消息队列辅线程,以及各个真正处理异步操作的工作线程。
JavaScript中线程运行机制详解
对于JavaScript我们都知道,他是个单线程语言,但是准确来说它是拥有一个执行程序主线程,和消息队列辅线程(Event Loop),以及各个真正处理异步操作的工作线程。
当主线程执行JS程序的时候,如果遇到了异步的操作(如:click事件,setTimeOut,I/0操作,异步请求,Promise等),主线程将各个异步任务交给工作线程,主线程继续执行,工作线程会判断是否到了要执行该异步操作的条件了,如果工作线程判断已经到了要执行工作线程的条件之后,就会把回调函数放入辅线程Event Loop的macrotask任务队列或者microtask任务队列的队尾。当上述主线程执行完后续同步调用的代码之后,辅线程会一直循环上面两个队列,首先执行的是microtask任务队列,而且该任务队列是该次循环就会执行完并清空的,macrotask会等到下次event loop循环的时候执行。
Example
1. console.log(1); 2. setTimeout(function timerCallback(){ 3. console.log(2); 4. },0) 5. new Promise(function execute(resolve,reject){ 6. console.log(3); 7. if(true) 8. resolve(); 9. }).then(function resolveCallback(){ 10. console.log(4); 11. }); 12. console.log(5); // 上面程序执行的顺序是:1,3,5,4,2
代码详解:当主线程执行上述代码的时候,从上往下执行:
1、先将console.log(1)这句代码做一个入栈执行的操作,打印出1,该句代码没有后续的方法调用了,就出栈销毁;
2、执行setTimeout,将改句代码入栈执行,判断到该方法属于WebAPIs(JS工作线程提供API的统称,其中包含了webcore工作模块提供了DOM Binding、network、timer等),timerCallback方法出栈,交给工作线程webcore下的timer模块,这里timer模块会判断是否到了执行条件了,由于是延时是0,所以timer模块判断可以执行了,并将回调函数timerCallback放到辅助线程Event Loop的macrotask队尾,等待下一次Event Loop循环去执行。
3、继续执行Promise这句代码(包括then语句),将其入栈执行,判断该Promise属于Promise模块(非WebAPIs),将其then的回调函数交给Promise模块,有后续调用;将execute方法入栈执行,有后续调用;将console.log(3)入栈执行,打印出3,console.log(3)执行完毕,出栈销毁;有后续调用if(true)入栈执行,判断为true,出栈销毁,继续将resolve()入栈执行,判断resolve()是WebAPIs的成功的回调,执行的时候通知到上面的Promise模块,Promise模块将成功的回调放到Event Loop的microtask队尾,resolve()出栈销毁,无后续调用,Promise出栈销毁。
4、继续执行,将console.log(5)入栈执行,打印出5,无后续调用,出栈销毁。
5、Event Loop开始循环microtask队列,将resolveCallback()入栈执行,有后续调用;将console.log(4)入栈执行,打印出4,出栈销毁;无后续调用,resolveCallback()出栈销毁,清空队列。
6、Event Loop开始循环macrotask队列,将timerCallback()入栈执行,有后续调用;将console.log(2)入栈执行,打印出2,出栈销毁,无后续调用;将timerCallback()出栈销毁,清空队列。
备注:macrotask任务队列的来源有:
setTimeout
setInterval
setImmediate
I/O
UI rendering
microtask任务队列的来源有:
process.nextTick
promises
Object.observe
MutationObserver
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/84305.html
摘要:从异步过程的角度看,函数就是异步过程的发起函数,事件监听函数就是异步过程的回调函数。事件触发时,表示异步任务完成,会将事件监听器函数封装成一条消息放到消息队列中,等待主线程执行。 1.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊。JavaScrip...
摘要:主线程在任务队列中读取事件,这个过程是循环不断地,所以这种运行机制叫做事件循环是在执行栈同步代码结束之后,下一次任务队列执行之前。 单线程 javascript为什么是单线程语言,原因在于如果是多线程,当一个线程对DOM节点做添加内容操作的时候,另一个线程要删除这个DOM节点,这个时候,浏览器应该怎么选择,这就造成了混乱,为了解决这类问题,在一开始的时候,javascript就采用单线...
摘要:机制详解与中实践应用归纳于笔者的现代开发语法基础与实践技巧系列文章。事件循环机制详解与实践应用是典型的单线程单并发语言,即表示在同一时间片内其只能执行单个任务或者部分代码片。 JavaScript Event Loop 机制详解与 Vue.js 中实践应用归纳于笔者的现代 JavaScript 开发:语法基础与实践技巧系列文章。本文依次介绍了函数调用栈、MacroTask 与 Micr...
摘要:上代码代码可以看出,不仅函数比指定的回调函数先执行,而且函数也比先执行。这是因为后一个事件进入的时候,事件环可能处于不同的阶段导致结果的不确定。这是因为因为执行完后,程序设定了和,因此阶段不会被阻塞进而进入阶段先执行,后进入阶段执行。 JavaScript(简称JS)是前端的首要研究语言,要想真正理解JavaScript就绕不开他的运行机制--Event Loop(事件环) JS是一门...
摘要:主线程从任务队列中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为事件循环。上面也提到,在到达指定时间时,定时器就会将相应回调函数插入任务队列尾部。这就是定时器功能。关于定时器的重要补充定时器包括与两个方法。 一、引子 本文介绍JavaScript运行机制,这一部分比较抽象,我们先从一道面试题入手: console.log(1); setTimeout(function()...
阅读 737·2021-10-09 09:44
阅读 2004·2021-09-22 15:54
阅读 5041·2021-09-22 10:55
阅读 1434·2019-08-29 18:41
阅读 771·2019-08-29 11:24
阅读 2099·2019-08-28 18:20
阅读 1024·2019-08-26 11:51
阅读 3043·2019-08-26 11:00