Skip to content

Latest commit

 

History

History
140 lines (89 loc) · 5.86 KB

基础知识.md

File metadata and controls

140 lines (89 loc) · 5.86 KB

基本原理

架构

nodejsstructure

3大基础要点:v8、Thread Pool、Event Loop

归纳:nodejs做为javascript运行环境,javascript是单线程的,说它在识别、解释代码的时候(接受任务),是单线程的,但它在从任务队列中获取执行具体任务的时候是多线程的,会将不同的任务分配给不同的线程处理

目录

1. 基本功能
2. Thread Pool
3. event loop
4. http.IncomingMessage
5. stream
6. events
7. error

1 基本功能

这里作简要功能总结

其中大部分都分同步异步

  1. 文件系统:能读写、创建、删除文件
  2. 子进程:执行命令、运行文件
  3. 进程:当前nodejs进程操作
  4. udp socket:udp实现的socket
  5. tcp socket: net, 实现网络功能
  6. 操作系统:当前os基础信息
  7. 加密:实现加密,加密算法等
  8. dns:实现dns的相关功能
  9. http/https:koa 实现的主要就是这一块功能,实现服务器
  10. events:nodejs 大体 api 都是基于事件实现的
  11. path: 文件与目录的路径处理

nodejs 运行机制:因为 nodejs 内置 v8 ,所以可以跑 js 代码,然后 js 可以调 node 环境的 node api;libuv 库负责 node api 的执行,将不同任务分配给不同的线程处理,这里就形成了 event loop 。

nodejs 的主要特点:事件驱动、单线程、异步i/0

单线程怎么解释?
异步 i/o ,也有同步 i/o ,比如 fs.appendFileSync()

2 Thread Pool

3 event loop

nodejs 的大部分api都是属于event loop的。许多都是 EventEmitter 类的实例,比如 net.Server , fs.ReadStream 等,都是采用了 eventEmitter.on() 方法用于注册监听器,然后用 eventEmitter.emit() 方法用于触发事件。

关键词:process.nextTick 事件队列 非阻塞i/o

3.1 nodejs 中的 event loop

time: 2018.11.09

先学习 nodejs 的事件

3.2 process.nextTick(func)

nodejs 事件循环,本次循环中,在调用栈任务执行完毕之后,在异步任务队列执行之前,会优先执行 nextTick 的任务,所有 nextTick 任务会在本轮事件循环中执行。并且 nextTick 任务的执行,会阻塞所有的 i/o 。

问:nextTick 内部嵌套的 nextTick 任务什么时候执行?
答:本轮事件中执行,也是优先于任务队列的其他任务的执行。因为在执行完毕调用栈中的任务时,会优先将 nextTick 中的任务放入调用栈中,让 v8 解释执行,如果此时又遇到 nextTick 任务,那么将其加入本轮事件循环,在当前 nextTick 任务执行完毕后,又会去判断,是否还有 nextTick 任务,如果没有,才会去执行异步任务队列中的其他任务。

3.3 nodejs eventloop vs browser eventloop

4 http.IncomingMessage

http.createServer(callback) 创建,可以在 callback 回调函数中使用 http.IncomingMessage 和 http.ServerResponse 2个对象,对应 koa 中就是 ctx.req 和 ctx.res 这2个对象,注意不是 ctx.request 和 ctx.response。http.IncomingMessage 实现了 可读流 接口。

5 stream

nodejs 提供了多种流对象,例如 http 服务器的请求process.stdout 都是流的实例。所有流都是 EventEmitter 的实例

5.1 什么是流

问题:流是什么类型,是一个对象吗,还是说只是一个概念?

答:nodejs 创建的流都是字符串或者 Buffer 的。自己实现的流也可以使用其他类型的 javascript 值(除了 null)。这些流默认是以对象模式进行操作

Buffer 是一个对象,用于暂存二进制数据。所以说流就是二进制数据对象集合或者字符串

5.2 流的缓冲

问:在使用 fs.createWriteStream 时,创建的流位于什么地方,最终是如何保存为一个文件的?

文件在网络传输中是以二进制数据传输的

答:可写流和可读流都会在内部的缓冲器中存储数据,然后由 writable.writableBuffer 或 readable.readableBuffer 来获取。

因为 Duplex 和 Transform 都是可读又可写的,所以他们维护着2个相互独立的内部缓冲器用于读取和写入。所以说现在缓冲器有3种

  1. 可读缓冲器
  2. 可写缓冲器
  3. 可读又可写缓冲器

5.3 流的基本类型

  1. Writable:可写入数据的流,比如 fs.createWriteStream()
  2. Readable:可读取数据的流,比如 fs.createReadStream()
  3. Duplex:可读又可写的流,比如 net.Socket
  4. Tranform:读写过程中可以修改,或转换数据的 Duplex 流,比如 zlib.createDeflate()

6 events

time: 2018.11.19

update: 2018.11.20

单独拿 events 出来,是因为 nodejs 所有能触发事件的对象都是 EventEmitter 类的实例,比如 net.Server 会在每次有新连接的时候触发事件,fs.ReadStream 会在文件被打开时触发事件

// events on-emit 模式
const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('触发事件');
});
myEmitter.on('error', (e) => {
  console.log(e);
});
myEmitter.emit('event');
  1. this 绑定:this 在监听回调事件中,默认指向 myEmitter 实例;如果是箭头函数,this指向是全局对象 global ,不是实例
  2. 事件同步、异步调用:默认是按照监听器注册的顺序同步调用所有监听器,使用 setImmediateprocess.nextTick 切换到异步(这里涉及到nodejs 的 event loop)
  3. eventEmitter.once():执行一次

7 error

参考文章

  1. nodejs 官网 event loop
  2. 阮一峰-再谈event loop
  3. nodejs 官网