浏览器中的Event Loop

首先咱们要知道浏览器是由什么组成的javascript

1.js主线程

1.1.heap(堆)

  • 堆:由操做系统自动分配释放 ,存放函数的参数值,局部变量的值等。特色先进后出(数组的shift方法)
let arr = [];
    arr.push(1);
    arr.push(2);
    console.log(arr.shift());   // 1
复制代码

1.2.stack(栈)执行上下文

  • 栈:会自动分配内存空间,会自动释放,存放基本类型,简单的数据段,占据固定大小的空间 特色先进后出(函数执行的销毁过程)
  • 当前栈也叫执行上下文(执行同步任务)

同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;java

alert("不关闭后面是不会执行的");
    console.log(1);
复制代码

2.WebAPIs (DOM,ajax,setTimeout)

3.callback queue(回调/任务 队列)

3.1任务队列的特色:先进先出,先放进去的异步任务先执行

setTimeout(()=>{
    console.log(1);
},300)
setTimeout(()=>{
    console.log(3);
},200)
setTimeout(()=>{
    console.log(2);
},200)
- 输出的结果是 3 2 1
复制代码

3.2任务队列里面存放的是异步任务(宏任务,微任务)

异步任务:不进入主线程、而进入"任务队列"的任务,只有"任务队列"通知主线程,某个异步任务能够执行了,该任务才会进入主线程执行。node

for(var i = 0; i < 5; i++){
        setTimeout(() =>console.log(i), 0);
    }
    console.log("ok");
    // 先输出ok,再输出5个5
复制代码
3.1.1异步任务的分类
  • 1.macro-task(宏任务): setTimeout, setInterval, setImmediate(ie), I/O MessageChannel
  • 2.micro-task(微任务): process.nextTick, 原生Promise,Object.observe(已废弃),MutationObserver(h5的一个方法,在dom更新完以后执行)
3.1.2异步任务的执行顺序

微任务的执行顺序在宏任务以前ajax

setTimeout(()=>{
    console.log("setTimeout1");
},0)
Promise.resolve().then(()=>{
    console.log("Promise");
})
process.nextTick(()=>{
    console.log("nextTick");
})
// 输出 nextTick Promise setTimeout1
复制代码

经过上面的了解咱们大体知道浏览器是先执行同步任务,执行完以后再执行异步任务。数组

回到主题,咱们来看看浏览器是怎么实现一个事件环(for)的

  • 1.全部同步任务都在主线程上执行,造成一个执行栈浏览器

  • 2.主线程以外,还存在一个任务队列。只要异步任务有了运行结果,就在任务队列之中放置一个事件dom

  • 3.一旦执行栈中的全部同步任务执行完毕,系统就会读取任务队列,将队列中的事件放到执行栈中依次执行异步

  • 4.主线程从任务队列中读取事件,这个过程是循环不断的函数

    整个的这种运行机制又称为Event Loop(事件循环)
    复制代码

看下面一段代码oop

setTimeout(function(){
    console.log('setTimeout1');
    Promise.resolve().then(()=>{
        console.log('then1');
    });
},0)
Promise.resolve().then(()=>{
    console.log('then2');
    Promise.resolve().then(()=>{
        console.log('then3');
    });
    setTimeout(function(){
        console.log('setTimeout2');
    },0)
})
// 输出结果 then2 then3 setTimeout1 then1 setTimeout2
复制代码

咱们得出一个结果

浏览器的事件环和任务队列里面微任务和宏任务的关系

  • 先执行栈中的内容 执行后 清空微任务
  • 取一个宏任务 再去清空微任务 ,再去取宏任务,一直到任务队列中没有为止

最后再说一下,node的事件环和任务队列里面微任务和宏任务的关系

  • 本质上和浏览器的事件环不变就是队列中微任务和宏任务的执行顺序有些差异
  • 先执行栈中的内容 执行后 清空微任务
  • 清空宏任务 再去清空微任务 ,再去清空宏任务,一直到任务队列中没有为止
相关文章
相关标签/搜索