对javascript EventLoop事件循环机制不一样的理解

前置知识点:

事件循环机制

相信读者读完以上推荐的文章后,已经知道事件循环机制是怎么一回事了吧,也能从容应对面试。接下来我要谈谈自己的理解:

为什么会有事件循环机制

  • js设计之初就是单线程模式,代码也都是顺序执行,当遇到因为大量计算、http请求等需要额外的等待时间时,浏览器用户就会体验到卡顿了,所以所有的设计和改进初衷只有一个就是要快

事件循环机制的产生

  • 浏览器说我的内核是多线程,可以辅助JS引擎线程啊,Web Worker线程提供大量计算辅助(不能操作DOM),事件触发线程定时触发器线程异步http请求线程


  • 执行栈(先进后出),由JS引擎线程控制,引用下面这个例子谈谈自己的理解:

    123456789101112131415161718
    console.log('script start');
    
    setTimeout(function() {  console.log('setTimeout');}, 0);
    
    Promise.resolve().then(function() {  console.log('promise1');}).then(function() {  console.log('promise2');});console.log('script end');
    
    // "script end"// "promise1"// "promise2"// "setTimeout"
  • ES5还没有Promise时代,异步回调很常见,上面例子中,通过解读Promise源码(前端面试必考题Promise的源码解析),我们可以把Promise转换成如下图式回调(个人理解,文章中的Promise源码也只是模拟,大部分浏览器已经原生支持)。
    1. 打印完script start, script end主执行栈出栈,如果Promise.resolve().then换成new Promise(executor),脑补Promise换成回调函数,那么这个函数一执行,executor函数也就执行了,然后遇到异步回调,回调函数被其它对应的线程接手,启动观察者模式,完成后回调函数被推入事件任务队列,等待执行栈空了进入主线程执行

    2. 以上这种在异步函数中放同步函数的例子,为了合理解释输出顺序而推出了microtasks微任务的概念,请看下面的例子,脑补Promise换成回调函数,Promise.prototype.then内部执行了return new Promise(),js引擎在捕捉到Promise时,放到了由js引擎自身控制的微任务队列等待执行,也就造成promise1、2、3、4错开打印

      123456789101112131415161718192021222324
      console.log('script start');
      
      new Promise(function(resolve, reject) {  console.log('promise1');  resolve();}).then(function() {  console.log('promise2');});
      
      new Promise(function(resolve, reject) {  console.log('promise3');  resolve();}).then(function() {  console.log('promise4');});
      
      console.log('script end');
      
      // "promise1"// "promise3"// "script end"// "promise2"// "promise4"
    3. micro 大专栏  对javascript EventLoop事件循环机制不一样的理解tasks微任务的概念完全为了解释异步函数中放同步函数的场景,而且各类文章和面试都是这种题目和例子,在实际开发过程中,你会在Promise中这么写么?,在我看来这种比较打印顺序太过于理论,而且可能会混乱你的思绪。就像下面的例子,Promiseresolve决定了Promise状态,就像在回调函数中满足了条件才会继续执行,例子中只是用setTimeout模拟异步请求,用之前的理论你可能觉得setTimeout被放入了事件任务队列,那没有resolvePromise怎么解释呢?(放到微任务里一直阻碍第一个setTimeout宏任务执行吗?显然是不可能的,这不是跟设计事件循环机制初衷冲突了么
      12345678910111213141516171819202122
      setTimeout(function() {  console.log('setTimeout');}, 0);
      
      new Promise(function(resolve, reject) {  setTimeout(function() { // 模拟异步请求    console.log('promise1');    resolve();  }, 0);}).then(function() {  console.log('promise2');});
      
      new Promise(function(resolve, reject) {  // resolve(); 注释掉resolve,使Promise一直处于‘pending’状态}).then(function() {  console.log('promise2');});
      
      // "setTimeout"// "promise1"// "promise2"
    4. 个人认为把Promiseasync/await脑补成原始的回调函数(模拟源码中模拟异步是用的setTimeout函数),而js引擎捕捉到setTimeout, setInterval就转给定时触发器线程处理,捕捉到XMLHttpReuqest, fetch就转给异步http请求线程,跟事件触发线程一起管理着事件任务队列,微任务的概念可以看作是当事件触发线程遇到几乎同时需要把回调函数放到事件任务队列时,Promise内部的异步标识函数优先级高于setTimeout函数吧,以上例子中没有执行resolvePromise状态一直处于’pending’,事件触发线程压根没有放入到事件任务队列,总之浏览器会安排的妥妥的,不要打架,虽然js引擎线程只有一个(听我指挥排好队,咱们这都是同步代码执行ms级别,我开了很多其它线程处理需要等待的代码了)。以下例子模拟所谓的几乎同时把回调函数放到事件任务队列,记得把Promise脑补成原始的回调函数。仿佛回到了没有微任务的时代。

      123456789101112131415161718192021222324252627
      setTimeout(function() {  console.log('setTimeout');}, 0);
      
      new Promise(function(resolve, reject) {  setTimeout(function() { // 模拟异步请求    console.log('promise1');    resolve();  }, 2000);}).then(function() {  console.log('promise2');});
      
      new Promise(function(resolve, reject) {  setTimeout(function() { // 模拟异步请求    console.log('promise3');    resolve();  }, 2000);}).then(function() {  console.log('promise4');});
      
      // "setTimeout"// "promise1"// "promise2"// "promise3"// "promise4"

以上内容纯属未深入了解js情况下的个人理解,感觉是在努力摒弃微任务的概念,回归ES5回调函数时代,便于自身理解事件循环机制而做出的遐想。

多环境下的事件循环机制

在node环境、浏览器环境以及各个不同版本下js引擎处理的方式还不太一样。node比浏览器还复杂些??(以后学Node.js时再看吧)

推荐阅读:

参考文章:

原文地址:https://www.cnblogs.com/lijianming180/p/12276070.html

时间: 2024-08-04 23:18:09

对javascript EventLoop事件循环机制不一样的理解的相关文章

深入理解JavaScript事件循环机制

前言 众所周知,JavaScript 是一门单线程语言,虽然在 html5 中提出了 Web-Worker ,但这并未改变 JavaScript 是单线程这一核心.可看HTML规范中的这段话: To coordinate events, user interaction, scripts, rendering, networking, and so forth, user agents must use event loops as described in this section. Ther

浏览器中的JavaScript事件循环机制

浏览器的事件循环机制是HTML中定义的规范. JavaScript有一个主线程和调用栈,所有的任务都会被放到调用栈等待主线程执行. JS调用栈 是一种先进后出的数据结构.当函数被调用时,会被添加到栈中的顶部,执行完成之后就从栈的顶部移除该函数,直到栈内被清空. 同步任务.异步任务 JS单线程任务分为同步任务和异步任务.同步任务会在调用栈中按照顺序排队等待主线程执行,异步任务则会在异步有了结果之后将注册的回调函数添加到任务队列(消息队列)中等待主线程空闲的时候,也就是栈内被清空的时候,被读取到栈中

JS JavaScript事件循环机制

区分进程和线程 进程是cpu资源分配的最小单位(系统会给它分配内存) 不同的进程之间是可以同学的,如管道.FIFO(命名管道).消息队列 一个进程里有单个或多个线程 浏览器是多进程的,因为系统给它的进程分配了资源(cpu.内存)(打开Chrome会有一个主进程,每打开一个Tab页就有一个独立的进程) 浏览器的渲染进程是多线程的 1.GUI渲染线程 2.JS引擎线程 3.事件触发线程 4.定时触发器线程 5.异步HTTP请求线程 事件循环机制 上图解释: 同步和异步任务分别进入不同的执行"场所&q

JavaScipt 中的事件循环机制,以及微任务 和宏任务的概念

说事件循环(event loop)之前先要搞清楚几个问题. 1. js为什么是单线程的? 试想一下,如果js不是单线程的,同时有两个方法作用dom,一个删除,一个修改,那么这时候浏览器该听谁的?这就是js被设计成单线程的原因. 2.js为什么需要异步? 如果js不是异步的话,由于js代码本身是自上而下执行的,那么如果上一行代码需要执行很久,下面的代码就会被阻塞,对用户来说,就是"卡死",这样的话,会造成很差的用户体验. 3.js是如何实现异步的? 既然js是单线程的,那么js是如何实现

js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)

javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环中的同步任务,异步任务: 同步和异步任务在不同的执行"场所",同步的进入主线程,异步的进入Event Table执行并注册函数. 当指定的异步事情完成时,Event Table会将这个函数移入Event Queue. 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,推

js事件循环机制辨析

?对于新接触js语言的人来说,最令人困惑的大概就是事件循环机制了.最开始这也困惑了我好久,花了我几个月时间通过书本,打代码,查阅资料不停地渐进地理解他.接下来我想要和大家分享一下,虽然可能有些许错误的地方,希望大家不吝赐教,感谢感谢. ?这是所涉及的知识点: 观察者模式 js的事件循环机制 js事件循环机制优缺点及与多线程的比较 观察者模式 ?js的事件循环机制是基于观察者模式的,而跟观察者模式相对应的是轮询,我们先来说说轮询的原理. ?我们将轮询映射在现实世界中即为:B不停到A的房间观察房间里

vue nextTick深入理解-vue性能优化、DOM更新时机、事件循环机制

一.定义[nextTick.事件循环] nextTick的由来: 由于VUE的数据驱动视图更新,是异步的,即修改数据的当下,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新. nextTick的触发时机: 在同一事件循环中的数据变化后,DOM完成更新,立即执行nextTick(callback)内的回调. 应用场景: 需要在视图更新之后,基于新的视图进行操作. 以上出现了事件循环的概念,其涉及到JS的运行机制,包括主线程的执行栈.异步队列.异步API.事件循环的协

Muduo网络库源码分析(一) EventLoop事件循环(Poller和Channel)

从这一篇博文起,我们开始剖析Muduo网络库的源码,主要结合<Linux多线程服务端编程>和网上的一些学习资料! (一)TCP网络编程的本质:三个半事件 1. 连接的建立,包括服务端接受(accept) 新连接和客户端成功发起(connect) 连接.TCP 连接一旦建立,客户端和服务端是平等的,可以各自收发数据. 2. 连接的断开,包括主动断开(close 或shutdown) 和被动断开(read(2) 返回0). 3. 消息到达,文件描述符可读.这是最为重要的一个事件,对它的处理方式决定

深入理解JavaScript的事件循环(Event Loop)

一.什么是事件循环 JS的代码执行是基于一种事件循环的机制,之所以称作事件循环,MDN给出的解释为 因为它经常被用于类似如下的方式来实现 while (queue.waitForMessage()) { queue.processNextMessage(); } 如果当前没有任何消息queue.waitForMessage 会等待同步消息到达 我们可以把它当成一种程序结构的模型,处理的方案.更详细的描述可以查看 这篇文章 而JS的运行环境主要有两个:浏览器.Node. 在两个环境下的Event