记录NodeJS八股文
说说对Node.js的理解?优缺点?应用场景?
理解
- 开源与跨平台的
JavaScript
运行时环境 - 在浏览器外运行V8 JavaScript引擎(Google Chrome的内核), 利用事件驱动、非阻塞和异步输入输出模型等技术提高性能;
优点
- 处理高并发场景性能更佳;
- 适合I/O密集型应用;
缺点
- 单线程, 不适合CPU密集型应用;
- 只支持单核CPU, 不能充分利用CPU;
- 可靠性低, 一旦代码某个环节崩溃, 整个系统都崩溃;
说说Node中的EventEmitter?如何实现一个EventEmitter?
Node
采用了事件驱动机制, 而EventEmitter
就是实现事件驱动的基础;
在EventEmitter
的基础上, Node
几乎所有的模块都继承了这个类, 这些模块拥有了自己的事件, 可以绑定/触发监听器, 实现了异步操作;
1 | // 实现一个自定义event |
EventLoop在浏览器与NodeJS的区别
结论
NodeJS版本 >= 11
之后就和浏览器保持一致;NodeJS版本 <= 10
, 浏览器和NodeJS环境下, 在microtask(微任务)任务队列的执行时机不同, 有不同的效果;
看题
1 | function test() { |
答案
1 | // node >= 11 && 浏览器 |
解析
我们就记住浏览器的EventLoop的机制就可以, 如果问到在NodeJS环境下的执行是什么, 我们可以来解析一下
- 在
NodeJS 版本 >= 11
以及浏览器下
- 执行test函数;
- 执行第一个setTimeout, 放入到宏任务中;
- 执行第二个setTimeout, 放入到宏任务中;
- 此刻微任务里面没有任务, 那么执行宏任务, 从队列的头部取出一个宏任务(第一个setTimeout);
- 打印children2, 此刻遇见Promise的then, 是微任务, 放入到微任务队列里面;
- 接下来我们发现微任务里面有任务了, 取微任务里面的任务, 打印出children2-1;
- 此刻微任务里面没有任务, 那么继续执行宏任务, 从任务队列的头部取出一个宏任务(第二个setTimeout);
- 打印children3, 此刻遇见Promise的then, 是微任务, 放入微任务队列里面;
- 接下来我们发现微任务里面有任务了, 取微任务里面的任务, 打印children3-1;
- 在
NodeJS版本 <= 10
下
- 执行test函数;
- 执行第一个setTimeout, 放入到宏任务里面;
- 执行第二个setTimeout, 放入到宏任务里面;
- 此刻微任务里面没有任务, 那么执行宏任务, 从队列的头部取出一个宏任务(第一个setTimeout);
- 打印children2, 此刻遇见Promise的then, 是微任务, 放入到微任务队列里面;
- 注意注意!!!此刻将会继续从队列的头部取出一个宏任务(第二个setTimeout);
- 打印children3, 此刻遇见Promise的then, 是微任务, 放入到微任务队列里面;
- 此刻微任务队列里有2个任务, 依次取出执行children2-1 children3-1;
大白话
它们的主要区别是执行微任务的时机不同, 假如此刻宏任务有2个任务AB, 此刻微任务队列什么都没有。如果是NodeJS版本 <= 10
下, 在执行A任务的时候产生了微任务W, A任务执行完毕, 那么会继续执行B, B执行完成之后再去执行微任务。而NodeJS版本 >= 11 && 浏览器
执行A任务, 产生了微任务, A执行完之后要去执行微任务。
简述什么是EventEmitter?
EventEmitter是Node.js中的一个核心模块, 主要用于处理事件相关的操作。它是事件驱动编程模式的一个实现, 提供了一种机制, 允许对象(也被事件发射器)发布(emit)事件, 而其他对象(也被称为监听器)可以订阅这些事件并定义当这些事件发生时应该执行的回调函数;
EventEmitter的主要功能包括事件的注册和监听、事件触发与传递参数, 以及事件的移除。通过调用EventEmitter的on或addListener方法, 可以将事件监听器绑定到特定的事件上。当使用EventEmitter的emit方法触发特定的事件时, 所有注册到该事件的监听器将会按照注册的顺序被调用, 并且可以传递参数给事件监听器。此外, 通过调用removeListener方法, 可以在不需要时移除特定事件的监听器;
EventEmitter是一种发布-订阅模式的实现, 也是一种观察者模式的实现。它充当了事件调度中心的角色, 是Node.js中实现异步操作的关键组件之一。
如何实现一个EventEmitter?
什么是EventEmitter?
在Node.js中, EventEmitter
是事件驱动的基础, 几乎所有模块都继承自它。它实现了观察者模式, 其中被观察者维护一组观察者, 并在更新时通知观察者;
EventEmitter
允许对象绑定和触发事件监听器, 实现异步操作。在Node.js中, 许多对象都会分发事件, 例如fs.readStream
对象会在文件被打开时触发一个事件;
使用EventEmitter
Node.js的events
模块提供了一个EventEmitter
类, 可以通过继承它创建自定义事件对象。
基本使用方法如下:
1 | const EventEmitter = require('events'); |
EventEmitter
的常用方法有:
on(eventName, listener)
:添加类型为eventName
的事件监听器;once(eventName, listener)
:添加类型为eventName
的事件监听器, 但只能执行一次, 执行后将被删除;prependListener(eventName, listener)
:添加类型为eventName
的事件监听器到事件数组头部;emit(eventName, ...args)
:触发类型为eventName
的事件监听器;removeListener(eventName, listener)
:移除类型为eventName
的事件监听器;
实现自定义EventEmitter
我们可以简单实现一个EventEmitter
类, 了解其基本原理。在实现过程中, 需要维护一个包含所有事件的对象events
。
1 | class EventEmitter { |
测试自定义EventEmitter
1 | const bus = new EventEmitter(); |
总结
EventEmitter
是Node.js中非常重要的一个模块, 它实现了事件驱动的基本模式, 让Node.js具备了处理异步操作的能力。