浏览器/nodeJS中的EventLoop

大家都知道JS是一门单线程语言,也就意味着JS无法进行多线程,但是JS中异步的概念完全可以模拟多线程,而且效果差不到哪去 #要完全理解异步,就需要了解 JS 的运行核心——事件循环(event loop) 但是在浏览器中运行JS和在nodeJS中运行还有一些差别,接下来我们就来看看这些差别在哪里

首先是浏览器中的EventLoop 在说浏览器EventLoop之前我们要先看看浏览器模型

  • 用户界面 包括地址栏,书签栏等那些东西
  • 浏览器引擎 在用户界面,呈现引擎之间传送指令
  • 渲染引擎 也被称为呈现引擎
  • 请求(网络) 用于网络调用,比如HTTP请求
  • JS解释器 用于解析和执行JS代码
  • UI(用户界面后端) 用于绘制样式 和JS共用一个线程
  • 数据存储 浏览器需要保存的一些数据 不如Cookie

JS和css公用一个线程是因为浏览器不会同时渲染JS和css,一般都会先渲染css再执行JS

浏览器中的微任务   then   messageChannel   mutationObersve

浏览器中的宏任务   setTimeout   setInterval

代码调用先进堆栈,堆栈是代码的总执行站,堆栈整个执行的过程中会先将微任务,宏任务放到相应的队列中,事件提出来等待触发,等到总执行站中的代码空了,会先看微任务队列中有没有,如果有就会放到总执行站中执行,然后在看宏任务队列中有没有。

setTimeout(function () {
    console.log('setTimeout')
})
Promise.resolve().then(function () {
      console.log('promise')
});
console.log('堆栈');

// 执行结果:
// 堆栈
// promise
// setTimeout
复制代码

如果把微任务队列放到堆栈中执行的时候又发现了宏任务,会顺便吧微任务中的宏任务一起执行了

setTimeout(function () {
    console.log('setTimeout1')
    Promise.resolve().then(function () {
        console.log('promise')
    });
})
setTimeout(function () {
    console.log('setTimeout2');
});

// 执行结果:
// setTimeout1
// promise
// setTimeout2
复制代码

然后是nodeJS运行环境中的EventLoop nodeJS中的宏任务和微任务在浏览器的基础上有新增了几个 微任务   then   nextTick   messageChannel   mutationObersve

宏任务   setTimeout   setInterval   setImmediate、

node的调用顺序中会比浏览器中的复杂一些

看图虽然复杂,但是我们只需要关心timers计时器阶段,poll轮询阶段,check检查阶段(setImmediate回掉),clons关闭阶段以及微任务队列即可,因为处理网络,内部调用与咱们的宏任务和微任务的执行没有太大的关系 和浏览器运行环境不同的是微任务只会在阶段转化的时候才会调用,就是close关闭阶段后再执行下一阶段的时候

process.nextTick(function () {
    console.log('nextTick')
});
setImmediate(function () {
    console.log('setImmediate')
});

// 执行结果:
// nextTick
// setImmediate
复制代码

如果宏任务执行的时候又发现微任务了,不会和浏览器一样顺便执行了,而是会将微任务再放到微任务队列中,等待整个阶段结束后,下一个阶段开始的时候先执行完微任务队列中的微任务

setTimeout(function () {
    console.log('setTimeout1')
    Promise.resolve().then(function () {
        console.log('promise')
    });
})
setTimeout(function () {
    console.log('setTimeout2');
});

// 执行结果:
// setTimeout1
// promise
// setTimeout2
复制代码

反之亦然

process.nextTick(function () {
    console.log(1)
    setImmediate(function () {
        console.log(2);
    })
})
setImmediate(function () {
    console.log(3);
    process.nextTick(function () {
        console.log(4)
    })
})

// 执行结果:
// 1
// 3
// 2
// 4
复制代码

timeout immediate 两个谁先执行不一定 取决于node的执行时间

setTimeout(function () {
    console.log('setTimeout');
})
setImmediate(function () {
    console.log('setImmediate')
});

// 执行结果:
// setTimeout
// setImmediate
// 或者:
// setImmediate
// setTimeout
复制代码

但是加上i/o文件操作以后就会先执行setImmediate,因为setImmediate在i/o文件操作后面的那个阶段执行,执行完setImmediate会在下一个阶段的时候再执行setTimeout (timers 计时器执行阶段)

let fs = require('fs');
fs.readFile('./1.txt', function () {
    console.log('fs');
    setTimeout(function () {
        console.log('setTimeout');
    })
    setImmediate(function () {
        console.log('setImmediate')
    })
});

// 执行结果
// fs
// setImmediate
// setTimeout
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值