博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一道事件环面试题引发的思考
阅读量:6983 次
发布时间:2019-06-27

本文共 2291 字,大约阅读时间需要 7 分钟。

直接上代码,想想下面的执行顺序

let fs = require('fs');setTimeout(function(){    Promise.resolve().then(()=>{        console.log('XXX2');    })},0);Promise.resolve().then(()=>{    console.log('XXX1');});fs.readFile('XXX',function(){    process.nextTick(function(){        console.log('nextTick')    })    setImmediate(()=>{        console.log('setImmediate')    });});复制代码

执行结果为

XXX1, XXX2, nextTick, setImmediate 复制代码

仔细想想为什么顺序是这样呢?

1: 首先我们要搞清楚Node.js 的Event Loop 到底是什么东西?

大家都知道JavaScript是单线程的,为什么是单线程的,因为要用 Javascript操作DOM,不可能对DOM操作加锁,这样使得JavaScript更加复杂,想想Java里面的并发包,就知道多线程环境并发操作是有多复杂了。

Node.js就是要让Javascript变为多线程的操作,所以就有了Event Loop,用来处理各种类型的回调函数,就是个执行非阻塞IO的一个操 作。既然都是多线程操作了,肯定就有线程调度和队列了。队列很 好理解,执行先进先出的回调函数的一个集合。

Node.js里有一个libuv,是一个高性能,事件驱动的IO跨平台的API 集合,是用C/C++写的,里面就是处理Event Loop的,调用操作系统的 API执行非阻塞IO操作。其实libuv底层还是有一些处理多线程所用到 的同步原语(互斥锁,读/写锁,信号量,内存屏障),还好我学过Java, 对这些都是非常了解的,尽管它是C++实现的。

2: 第二步,需要理解什么是microtask,什么是macrotask ?

为什么要有microtask和macrotask呢,是因为线程要调度嘛,把线程 调度的不同形态分成了两类,一类是microtask,一类是macrotask。 而在Node.js中,有很多是用来协调异步任务的,例如:setTimeout, setImmediate,process.nextTick,setInterval,Promise.resolve.t hen()。Node.js里规定microtask是比macrotask先执行的。 附上一张运行顺序图:

┌───────────────────────────────────┐┌─>│timers(计时器)执行                  ││  |setTimeout以及setInterval的回调     | ----- 1│  └──────────┬────────────────────────┘│  ┌──────────┴────────────┐│  │     I/O callbacks     ││   处理网络,流,TCP的错误  │  ----------------2│  │      callback      ││  └──────────┬────────────┘│  ┌──────────┴────────────┐│  │     idle, prepare     ││  │    node内部使用        │-------------------3│  └──────────┬────────────┘      ┌───────────────┐│  ┌──────────┴────────────┐      │   incoming:   ││  │poll(轮询)            │<─────┤  connections, ││  │ 执行poll中的i/o队列检查 │      │data, etc.    │-----4│  │定时器是否到时          │      └───────────────┘│  └──────────┬────────────┘          │  ┌──────────┴────────────┐      │  │        check          ││  │  存放setImmediate回调  │-------------------5│  └──────────┬────────────┘│  ┌──────────┴────────────┐└──┤    close callbacks    │  │ 关闭的回调例如         │-------------------6  │ socket.on('close')    │  └───────────────────────┘复制代码

在上面的图中,我们只需考虑1,4,5的时期,在最上面代码中,Promise.resolve().then()属于microTask,而setTimeout和setImmediate属于macroTask,显然,问题就迎刃而解了。

转载于:https://juejin.im/post/5b6906585188251b186be728

你可能感兴趣的文章
HDOJ 2041 超级楼梯
查看>>
1108File Space Bitmap Block损坏能修复吗2
查看>>
遭遇DBD::mysql::dr::imp_data_size unexpectedly
查看>>
人人都会设计模式:03-策略模式--Strategy
查看>>
被忽视但很实用的那部分SQL
查看>>
解读阿里云oss-android/ios-sdk 断点续传(多线程)
查看>>
ML之监督学习算法之分类算法一 ——— 决策树算法
查看>>
骡夫电商地址
查看>>
亚信安全火力全开猎捕“坏兔子”,全歼详解
查看>>
[二]RabbitMQ-客户端源码之AMQConnection
查看>>
通过添加HTTP Header实现上下文数据在WCF的自动传递
查看>>
Emacs之魂(三):列表,引用和求值策略
查看>>
【ARM】一步一步移植Linux Kernel 2.6.13到板子
查看>>
智能家居——IoT零基础入门篇
查看>>
《Linux From Scratch》第一部分:介绍 第一章:介绍-1.3. 更新日志
查看>>
阿里将在雄安新区设3家子公司:涉AI、蚂蚁金服和菜鸟;北航设立全国首个人工智能专业,与百度合作办学...
查看>>
Powershell指令集_2
查看>>
归并排序算法
查看>>
北京第一个公共云计算平台即将诞生
查看>>
5G频谱相争“兵戎相见”各相部署风起云涌
查看>>