Js中eventLoop的循环机制

  • 堆(Heep)

    • 堆是一种数据结构,是利用二叉树维护的一组数据,堆分为两种,一种为最大堆,一种为最小堆,将根节点最大的堆称之为最大堆或大根堆,根节点最小的堆,叫做最小堆或者小根堆,堆是线性数据结构,相当于一维数组,有唯一后继

    在这里插入图片描述

  • 栈(Stack)

    • 栈,是在计算机科学中限定仅在表尾进行插入,或者是删除操作的线性表,栈是一种数据结构,它按照后进先出的原则存储数据,先进入的数据压入栈底,最后的数据在栈顶,需要读数据的时候,从栈顶开始弹出数据,栈是只能在某一端插入和删除的特殊线性表

    在这里插入图片描述

  • 队列(Queue)

    • 队列,其特殊之处在于,只允许在表的前端(front)进行删除操作,而在表尾(rear)进行插入操作,和堆栈一样,是一种受限的线性表,进行插入操作的端,叫做队尾,进行删除操作的端,叫做队头,队列中不存在元素时,称之为空队列

    • 队列的数据元素,称之为队列元素,在队列中插入一个队列元素,称之为入队,队列中删除一个元素,称之为出队,因为队列只允许在一端插入,在另外一端删除,所以只有最早进入队列的元素,才能从队列中删除,故队列称之为先进先出

在这里插入图片描述

  • 宏任务(MacroTask)

    • script全部代码、setTimeoutsetIntervalsetImmediate(浏览器暂时不支持,只有IE10支持,具体可见MDN)、I/OUI Rendering
  • 微任务(MicroTask)

    • Process.nextTick(Node独有)PromiseObject.observe(废弃)MutationObserver
  • 浏览器中的EventLoop

    • Javascript 有一个 main thread 主线程和 call-stack 调用栈(执行栈),所有的任务都会被放到调用栈等待主线程执行
  • js调用栈

    • JS调用栈采用的是后进先出的规则,当函数执行的时候,会被添加到栈的顶部,当执行栈执行完成后,就会从栈顶移出,直到栈内被清空
  • 同步任务和异步任务

    • Javascript单线程任务被分为同步任务异步任务,同步任务会在调用栈中按照顺序等待主线程依次执行,异步任务会在异步任务有了结果后,将注册的回调函数放入任务队列中等待主线程空闲的时候(调用栈被清空),被读取到栈内等待主线程的执行

    在这里插入图片描述

    • 任务队列Task Queue,即队列,是一种先进先出的一种数据结构

在这里插入图片描述

  • 事件循环的事件模型

    • 选择当前要执行的任务队列,选择任务队列中最先进入的任务,如果任务队列为空即null,则执行跳转到微任务(MicroTask)的执行步骤。
    • 将事件循环中的任务设置为已选择任务。
    • 执行任务。
    • 将事件循环中当前运行任务设置为null。
    • 将已经运行完成的任务从任务队列中删除。
    • microtasks步骤:进入microtask检查点。
    • 更新界面渲染。
    • 返回第一步。
  • 执行栈进入microtask检查点时,用户代理会执行以下步骤

    • 设置microtask检查点标志为true。

    • 当事件循环microtask执行不为空时:选择一个最先进入的microtask队列的microtask,将事件循环的microtask设置为已选择的microtask,运行microtask,将已经执行完成的microtasknull,移出microtask中的microtask

    • 清理IndexDB事务

    • 设置进入microtask检查点的标志为false

    • 在这里插入图片描述

    • 执行栈在执行完同步任务以后,查看执行栈是否为空,如果执行栈为空,就会去执行task(宏任务)每次宏任务执行完毕以后,检查是否存在微任务(microTask)队列是否为空,如果不为空的话,会按照先进先出的规则全部执行完毕微任务(microTask)后,设置微任务(microTask)队列为null然后再去执行宏任务,如此循环,就形成了事件循环(EventLoop)

  • 举个栗子

    • 请说出以下代码输出的结果

      console.log('1');
      setTimeout(function() {
        console.log('2');
      }, 0);
      // resolve是一个同步任务,后面虽然调用了then方法,但是执行顺序还是先去执行同步任务,然后再去执行异步任务
      Promise.resolve().then(function() {
        console.log('3');
      }).then(function() {
        console.log('4');
      });
      console.log('5');
      // 1 5 3 4 2
      
  • 第一次执行

    • (执行同步代码,将宏任务(Task)微任务(Microtasks)划分到各自的队列中)
        Tasks:run script、 setTimeout callback
        
        Microtasks:Promise then	
        
        JS stack: script	
        Log: script start、script end。
    
  • 第二次执行

    • 执行宏任务后,检测到微任务(Microtasks)队列中不为空,执行Promise1,执行完成Promise1后,调用Promise2.then,放入微任务(Microtasks)队列中,再执行Promise2.then
        Tasks:run script、 setTimeout callback
        
        Microtasks:Promise2 then	
        
        JS stack: Promise2 callback	
        Log: script start、script end、promise1、promise2
    
  • 第三次执行

    • 当微任务(Microtasks)队列中为空时,执行宏任务(Tasks),执行setTimeout callback,打印日志
        Tasks:setTimeout callback
        
        Microtasks:	
        
        JS stack: setTimeout callback
        Log: script start、script end、promise1、promise2、setTimeout
    
  • 第四次执行

    • 清空Tasks队列和JS stack
        Tasks:setTimeout callback
        
        Microtasks:	
        
        JS stack: 
        Log: script start、script end、promise1、promise2、setTimeout
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值