非阻塞IO与阻塞IO
-
IO就是输入—输出
-
操作系统通常提供了两种调用方式,阻塞调用和非阻塞调用
- 阻塞式调用: 调用结果返回之前,当前线程处于阻塞态(阻塞态CPU不会分配时间片),调用线程只有在得到调用结果之后才会继续执行
- 非阻塞式调用:调用执行之后,当线程不会停止执行,只需要过一段时间来检查一下有没有结果返回即可。
-
非阻塞式调用的问题
- 我们没有获取到结果,因为是异步的
- 我们为了得到完整的数据,需要频繁的去确定度渠道的数据是否完整
- 这歌过程角轮训操作
-
kibuv提供了一个线程池
- 线程池会负责所有相关的操作,并且会轮训或者其他的方式等待结果。
- 当获取奥结果的时候,就可以将对应的回掉放回到事件循环(某一个事件队列)中。
- 事件循环就可以负责接管后续的回掉工作,让应用程序执行对应的回掉函数。
-
阻塞于非阻塞对于被调用者,即系统层面,系统为程序提供了阻塞调用和非阻塞调用,同步和异步是对于调用者,就是自己的程序,发七调用,没有其他操作,只是等待结果这个过程就是同步,发起调用后会等待结果,继续完成其他的工作,等有回掉再执行,这个过程就是异步的。
-
不需要关注线程安全问题。
-
微任务队列:
- next tick queue: process.nextTick;
- other queue: Promis的then。queueMicrotash
-
宏观任务队列:
- timer queue,settimeout…;
- poll queue: IO事件;
- check queue: setImmediate ;
- Close queue: 回掉函数close 事件
-
事件队列初始化
setTimeout( fn1 ) setImmediate( fn2 ) // 理论上是fn1() >>> fn2() // 先会将setTimeout的回掉内容挂在到事件树上去,放入队列中,但是这个过程需要消耗时间 // 当同步代码执行完成,此时,就会初始化事件循环 这个过程需要消耗时间 // 开始第一次tick 会一次执行setTimeout 然后会有一个check过程,检测是否有setImmediate,有就执行setImmediate; // 假设 同步代码执行完成后,时间循环初始化的时间快于setTimeout回掉挂在到队列树上的时候,就会出现 fn2() >>> fn1() // 初始化事件循环队列后就会立马开始执行,遇到check后检测是否有setImmediate,就会执行setImmediate,不会等待setTimeout挂在到队列树上之后在执行,
八. Stream
-
文件的二进制数据如同流水一样被拉去到程序中,即字节流
-
所有的流都是EventEmitter的实例
-
http模块的Request和response,process.stdout对象
-
stream初次尝试
-
// 流的方式读取文件 const reader = fs.createReadStream("path", { start: 2, end: 10, highWaterMark: 2 // 每次读取多少 }); reader.on("data", data => { console.log(data); reader.pause() // 暂停读取 reader.resume() // 开始读取 }) reader.on("opne",fn) reader.on("close",fn)
-
pipe可以将读取出来的流全部写入
const reader = fs.createReadStream("path") const reader = fs.createWriteStream("path") reader.pipe(writer);
-