与非阻塞"/>
Nodejs 中的同步与异步、阻塞与非阻塞
在 Nodejs 的学习过程中,我们经常会听到同步异步,阻塞和非阻塞。那什么是同步和异步?什么是阻塞和非阻塞呢?
Nodejs是单线程的异步事件驱动的Js运行时,使用事件循环的方式,将操作交给系统内核处理,当操作完成后内核通知Nodejs讲合适的回调函数添加到轮询队列中等待回调执行。而阻塞,在官方教程中也有说明
阻塞 是指在 Node.js 程序中,其它 JavaScript 语句的执行,必须等待一个非 JavaScript 操作完成。这是因为当
阻塞 发生时,事件循环无法继续运行 JavaScript。在 Node.js 中,JavaScript 由于执行 CPU 密集型操作,而不是等待一个非 JavaScript 操作(例如
I/O)而表现不佳,通常不被称为 阻塞。在 Node.js 标准库中使用 libuv 的同步方法是最常用的 阻塞 操作。原生模块中也有 阻塞
方法。在 Node.js 标准库中的所有 I/O 方法都提供异步版本,非阻塞,并且接受回调函数。某些方法也有对应的 阻塞 版本,名字以 Sync
结尾。–
阻塞对比非阻塞一览:
很明显可以看出,所谓的非 JavaScript 操作既不是ES中规定的API操作。所以像for循环,数值计算,这种并不算是阻塞。而标准库中所有的Sync方法是非 JavaScript 操作操作,会阻塞主线程的JS代码运行。
在Nodejs中,我们常听到异步回调,到底什么是异步回调?在js中,回调是通过执行传入的方法,既等到操作执行完,会通过回调方法通知。既然有异步回调也会有同步回调。
function func1(num, callbacll = result => result) {callbacll(num ** 2);
}
console.log("start");
func1(2, res => {console.log(res);
});
console.log("end");
// start
// 4
// end
同步既执行顺序与代码编写顺序相符的。而异步则是执行顺序与代码编写顺序不符。但是同步回调可直接写成下面这样子,所以一般同步回调使用的场景几乎没有。
function func1(num) {return num ** 2;
}
console.log("start");
console.log(func1(2));
console.log("end");
// start
// 4
// end
那看看异步回调是怎么样的。
const fs = require("fs");
console.log("start");
fs.readFile("./1.js", (err, data) => {if (err) {throw err;}console.log("data");
});
console.log("end");
// start
// end
// data
其中readFile的第二个参数就是异步回调方法。虽然叫异步回调方法,但是也是在主线程执行的,毕竟事件轮询调用这个回调方法是用来通知主线程的。
非阻塞方法需要异步回调方法通知主线程,阻塞方法直接阻塞Js主线程。阻塞和非阻塞都为非 JavaScript 操作,JavaScript 操作不能成为阻塞和非阻塞。
因为非阻塞需要异步回调函数通知主线程,当一个操作流程需要一连串的IO和网络操作,并且这些IO和网络操作都需要严格按照一定执行时,就会出现回调地狱。为了解决这个问题,人们给异步回调披上Promise的外衣,实现了链式调用,把异步回调用then的方式执行,把多行代码压成一行。但是依然不如同步代码一样看起来直观,所以人们有给Promise装一个箱子,就是async和await。
更多推荐
Nodejs 中的同步与异步、阻塞与非阻塞
发布评论