详解JS浏览器事件循环机制

 更新时间£º2019年03月27日 11:13:33   作者£º我爱吃方方面   我要评论

这篇文章主要介绍了JS浏览器事件循环机制£¬文中通过示例代码介绍的非常详细£¬对大家的学习或者工作具有一定的参考学习价值£¬需要的朋友们下面随着小编来一起学习学习吧

先来明白些概念性内容¡£

进程¡¢线程

进程是系统分配的独立资源£¬是 CPU 资源分配的基本单位£¬进程是由一个或者多个线程组成的¡£

线程是进程的执行流£¬是CPU调度和分派的基本单位£¬同个进程之中的多个线程之间是共享?#23186;?#31243;的资源的¡£

浏览器内核

浏览器是多进程的£¬浏览器每一个 tab 标签都代表一个独立的进程£¨也不一定£¬因为多个空白 tab 标签会合并成一个进程£©£¬浏览器内核£¨浏览器渲染进程£©属于浏览器多进程中的一种¡£

浏览器内核有多种线程在工作¡£

GUI 渲染线程:

  1. 负责渲染页面£¬解析 HTML£¬CSS 构成 DOM 树等£¬当页面重绘或者由于某种操作引起回流都会调起该线程¡£
  2. 和 JS 引擎线程是互斥的£¬当 JS 引擎线程在工作的时候£¬GUI 渲染线程会被挂起£¬GUI 更新?#29615;?#20837;在 JS 任务队列中£¬等待 JS 引擎线程空闲的时候继续执?#23567;?/li>

JS 引擎线程:

  1. 单线程工作£¬负责解析运行 JavaScript 脚本¡£
  2. 和 GUI 渲染线程互斥£¬JS 运行耗时过长就会导致页面阻塞¡£

事件触发线程:

当事件符合触发条件被触发时£¬该线程会把对应的事件回调函数添加到任务队列的队尾£¬等待 JS 引擎处理¡£

定时器触发线程:

  1. 浏览器定时计数器并不是由 JS 引擎计数的£¬阻塞会导致计时不准确¡£
  2. 开启定时器触发线程来计时并触发计时£¬计时完成后会被添加到任务队列中£¬等待 JS 引擎处理¡£

http 请求线程:

  1. http 请求的时候会开启一条请求线程¡£
  2. 请求完成有结果了之后£¬将请求的回调函数添加到任务队列中£¬等待 JS 引擎处理¡£

 

JavaScript 引擎是单线程

JavaScript 引擎是单线程£¬也就是说每次只能执行一项任务£¬其他任务都得按照顺序排队等待被执行£¬只有当前的任务执行完成之后才会往下执行下一个任务¡£

HTML5 中提出了 Web-Worker API£¬主要是为了解决页面阻塞问题£¬但是并没有改变 JavaScript 是单线程的本质¡£了解 Web-Worker¡£

JavaScript 事件循环机制

JavaScript 事件循环机制分为浏览器和 Node 事件循环机制£¬两者的实现技术不一样£¬浏览器 Event Loop 是 HTML 中定义的规范£¬Node Event Loop 是由 libuv 库实现¡£这里主要讲的是浏览器部分¡£

Javascript 有一个 main thread 主线程和 call-stack 调用栈(执行栈)£¬所有的任务都会?#29615;?#21040;调用栈等待主线程执?#23567;?/p>

JS 调用栈

JS 调用栈是一种后进先出的数据结构¡£当函数被调用时£¬会被添加到栈中的顶部£¬执行完成之后就从栈顶部移出该函数£¬直到栈内被清空¡£

同步任务¡¢异步任务

JavaScript 单线程中的任务分为同步任务和异步任务¡£同步任务会在调用栈中按照顺序排队等待主线程执行£¬异步任务则会在异步有了结果后将注册的回调函数添加到任务队列(消息队列)中等待主线程空闲的时候£¬也就是栈内被清空的时候£¬被读取到栈中等待主线程执?#23567;?#20219;务队列是先进先出的数据结构¡£

Event Loop

调用栈中的同步任务都执行完毕£¬栈内被清空了£¬就代表主线程空闲了£¬这个时候就会去任务队列中按照顺序读取一个任务放入到栈中执?#23567;?#27599;次栈内被清空£¬都会去读取任务队列有没有任务£¬有?#25237;?#21462;执行£¬一直循环读取-执行的操作£¬就形成了事件循环¡£

定时器

定时器会开启一条定时器触发线程来触发计时£¬定时器会在等待了指定的时间后将事件放入到任务队列中等待读取到主线程执?#23567;?/p>

定时器指定的延时毫秒数其实并不准确£¬因为定时器只是在到了指定的时间时将事件放入到任务队列中£¬必须要等到同步的任务和现有的任务队列中的事件全部执行完成之后£¬才会去读取定时器的事件到主线程执行£¬中间可能会存在耗时比较久的任务£¬那么就不可能保证在指定的时间执?#23567;?/p>

宏任务(macro-task)¡¢微任务(micro-task)

除了广义的同步任务和异步任务£¬JavaScript 单线程中的任务可以细分为宏任务和微任务¡£

macro-task包括£ºscript(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering¡£

micro-task包括£ºprocess.nextTick, Promises, Object.observe, MutationObserver¡£

console.log(1);
setTimeout(function() {
  console.log(2);
})
var promise = new Promise(function(resolve, reject) {
  console.log(3);
  resolve();
})
promise.then(function() {
  console.log(4);
})
console.log(5);

示例中£¬setTimeout 和 Promise被称为任务源£¬来自不同的任务源注册的回调函数会?#29615;?#20837;到不同的任务队列中¡£

有了宏任务和微任务的概念后£¬那 JS 的执行顺序是怎样的£¿是宏任务先还是微任务先£¿

第一次事件循环中£¬JavaScript 引擎会把整个 script 代码当成一个宏任务执行£¬执行完成之后£¬再检测本次循环中是否寻在微任务£¬存在的话就?#26469;?#20174;微任务的任务队列中读取执行完所有的微任务£¬再读取宏任务的任务队列中的任务执行£¬再执行所有的微任务£¬如此循环¡£JS 的执行顺序就是每次事件循环中的宏任务-微任务¡£

  1. 上面的示例中£¬第一次事件循环£¬整段代码作为宏任务进入主线程执?#23567;?/li>
  2. 遇到了 setTimeout £¬就会等到过了指定的时间后将回调函数放入到宏任务的任务队列中¡£
  3. 遇到 Promise£¬将 then 函数放入到微任务的任务队列中¡£
  4. 整个事件循环完成之后£¬会去检测微任务的任务队列中是否存在任务£¬存在就执?#23567;?/li>
  5. 第一次的循环结果打印为: 1,3,5,4¡£
  6. 接着再到宏任务的任务队列中按顺序取出一个宏任务到栈中让主线程执行£¬那么在这次循环中的宏任务就是 setTimeout 注册的回调函数£¬执行完这个回调函数£¬发现在这次循环中并不存在微任务£¬就准备进行下一次事件循环¡£
  7. 检测到宏任务队列中已经没有了要执行的任务£¬那么就结束事件循环¡£
  8. 最终的结果就是 1,3,5,4,2¡£

以上所述是小编给大家介绍的JS浏览器事件循环机制详解整合£¬希望对大家有所帮助£¬如果大家有任?#25105;?#38382;请给我留言£¬小编会及时回复大家的¡£在此也非常?#34892;?#22823;家对脚本之家网站的支持£¡

相关文章

  • 跨域请求的完美解决方法(JSONP, CORS)

    跨域请求的完美解决方法(JSONP, CORS)

    下面小编就为大家带来一篇跨域请求的完美解决方法(JSONP, CORS)¡£小编觉得挺不错的£¬现在就分享给大家£¬也给大家做个参考¡£一起跟随小编过来看看吧
    2016-06-06
  • 详解js闭包

    详解js闭包

    闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实在是比较晦涩,对我来说也是一样.
    2014-09-09
  • Zero Clipboard js+swf实现的复制功能使用方法

    Zero Clipboard js+swf实现的复制功能使用方法

    如?#38382;?#29992; Zero Clipboard ,其实注意测试环境要在 web环境中¡£
    2010-03-03
  • JavaScript中的对象与JSON

    JavaScript中的对象与JSON

    这篇文章主要介绍了JavaScript中的对象与JSON,本文讲解了定义JSON与javascript对象¡¢javascript对象转换为JSON¡¢javascript中解析JSON等内容,需要的朋友可以参考下
    2015-07-07
  • 网页收藏夹显示ICO图标£¨代码少£©

    网页收藏夹显示ICO图标£¨代码少£©

    在添加网页到收藏夹之后会看到一个漂亮的图标£¬很好奇是怎?#35789;?#29616;的呢£¿下面小编就给大家讲解下网页收藏夹显示ICO图标£¨代码少£©£¬有需要的小伙伴可以来参考下
    2015-08-08
  • Javascript图像处理¡ª亮度对比度应用案例

    Javascript图像处理¡ª亮度对比度应用案例

    上一篇文章£¬我们讲解了图像处理中的卷积操作和平滑£¨也就是模糊£©处理£¬这篇文章我们进行亮度和对比度的变化,有需要的朋友可以参考下
    2013-01-01
  • javascript中join方法实例讲解

    javascript中join方法实例讲解

    在本篇内容里小编给大家分享了关于javascript中join方法实例内容£¬需要的朋友们学习参考下¡£
    2019-02-02
  • JavaScript入门教程(4) js浏览器对象

    JavaScript入门教程(4) js浏览器对象

    navigator 浏览器对象£¬包含了正在使用的 Navigator 的版本信息¡£?#20174;?#20102;当前使用的浏览器的资料¡£JavaScript 客户端运行时刻引擎自动创建 navigator 对象¡£
    2009-01-01
  • 查询json的数据结构的8种方式简介

    查询json的数据结构的8种方式简介

    你有没有对¡°在复杂的JSON数据结构中查?#31227;?#37197;内容¡±而烦恼,这篇文章介绍了查询json的数据结构的8种方式,总有一个适合你项目使用的方法
    2014-03-03
  • a标签的href与onclick事件的区别详解

    a标签的href与onclick事件的区别详解

    对于a标签的href与onclick事件,大家都经常见到£¬也经常使用,可它们有什么区别呢?下面就让小编来给大家详细介绍下,?#34892;?#36259;的朋友可以学习下£¬不用谢了£¬哈哈
    2014-11-11

最新评论

ÁÉÄþ35Ñ¡7¿ª½±½á¹û