javascript运行机制:Event Loop

js是单线程的

  • 因为是单线程,所以所有任务都需要排队,前一个任务结束,后一个任务才能执行,如果前一个任务花费时间较长,后一个任务等待时间也随之变长。
  • js可以做到先把等待中的任务先放一边晾着,去处理后面的任务。
  • 于是所有任务可以分为两种,一种是同步任务,另一种是异步任务:
    • 同步任务很简单,前面的任务完成后面才能执行,一个接一个的执行任务。
    • 异步任务不占用主线程,直接进入“任务队列”中,等任务队列通知主线程,某个任务可以执行了,才会进入主线程执行。
异步执行的运行机制
  1. 所有同步任务都在主线程上执行,形成一个执行栈
  2. 主线程之外,还存在一个“任务队列”。只要异步任务有了执行结果,就在“任务队列”中放置一个事件
  3. 一旦执行栈中的所有同步任务都执行完毕,就会去“任务队列”中读取新的任务放到执行栈中,再依次执行任务
  4. 只要主线程空了,就会读取任务队列,这就是js的运行机制。这个过程会不断的重复
再说说事件和回调函数
  • 任务队列其实存放的是事件的队列,主程序读取任务队列,其实就是在读有哪些事件罢了
  • 只要指定过回调函数,这些事件发生时就会进入任务队列中,等待主线程读取
  • 异步任务必须指定回调函数,当主线程执行异步任务时,其实就是在执行对应的回调函数
  • 任务队列是一个先进先出的数据结构,排在前面的先执行。当调用栈中的任务空了后,主线程会自动调用任务队列里的任务执行
来看看Event Loop
  • 主线程从任务队列中读取任务,这个过程是不断重复的,所以被称为Event Loop(事件循环),从字面意思就清楚了
  • 再来看一张图

上图中,主线程产生了heap(堆)和stack(栈),栈中的代码调用各种api,然后在任务队列中加入click,load,done等事件,当栈中的任务都执行完后就去调用任务队列中的事件并依次执行

function one() {
    var a = 1;
    two();
    function two() {
        var b = 2;
        three();
        function three() {
            console.log(b);
        }
    }
}

one();
// 栈:是先进后出 函数调用就是最常见的形式
// one -> two -> three 依次执行
// 销毁过程是three -> two -> one
复制代码
任务队列中的定时器
console.log(1);
setTimeout(function () {
    console.log('定时器');
},0);      // 如果不写时间,默认是4ms
let p = new Promise(function (resolve, reject) {
    console.log(3);
    resolve(100);
}).then(function (data) {
    console.log(data);
});
console.log(2);
// 1 3 2 100 '定时器' 
复制代码

Node

先来看看node是如何工作的

NodeJs的运行机制:
  1. V8引擎解析js代码
  2. 代码中可能会调用node API,node会交给LIBUV库处理
  3. LIBUV通过阻塞I/O和多线程实现了异步I\O
  4. 将任务的执行结果返回给V8引擎,V8引擎再将结果返回给用户
Node中的Event Loop

在LIBUV内部有这样一个事件环机制,在node启动时会初始化事件环

  • 这里每一个阶段都对应一个事件队列,当Event Loop执行到某一阶段的时候会将该阶段对应的事件依次执行。
  • 当队列执行完毕or执行的数量超过上限的时候,会自动转入下一阶段。 这里我们重点关注一下poll阶段
poll阶段

总结一下:以上内容就是关于事件环的整体流程,也可以理解一下同步和异步的区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值