前言
目前Node在前端开发中占据重要的地位,不管在我们的weback vite
等打包构建工具中作为基础运行环境,还是koa express egg.js Nest.js
等服务端框架中充当中间层
或者后端服务器
,总之,现在Node.js
能做的事情越来越多了,所以学习Node肯定是必要的。
Node简介
简单来说,Node
就是一个运行时环境
,底层是Google Chrome的V8 JavaScript引擎
。
这时候你可能会有疑问了,为什么使用javascript
去实现node,而不用其他Java PHP C
等后端语言呢?
为什么选择JavaScript成为Node的实现语言?
这时候就要提到Node的作者Ryan Dahl
了,其实他是一名资深的C/C++程序员,他的工作重点就是如何设计高性能服务器。而设计高性能服务器有两个要点:一个是事件驱动 ,另一个是非阻塞I/O。
Ryan Dahl
当时对一些语言进行了评估:
- C:C的开发门槛高,不会有太多的开发者能将它用于日常的业务开发
- Haskell: Ryan Dahl觉得自己还不足够玩转它
- Lua:Lua自身已经有很多的阻塞I/O库,在这基础上构建非阻塞I/O库很难有市场
- Ruby: Ruby的虚拟机性能不好
而选择JavaScript的原因是:
- 高性能:Chrome的V8在第二次浏览器大战中性能第一,并且是基于BSD许可证发布的。
- 符合时间驱动:JavaScript在浏览器中有许多的事件驱动。
- 没有历史包袱:虽然服务端JavaScript存在了很多年,但后端部分一直没有市场。
Node的特点
Node主要有四大特点:
1. 异步I/O
Node的IO操作都是异步的,我们需要等待异步回调的结果,比如我们使用Node内置模块fs
去读取文件内容,我们需要在异步会调用才能拿到读取的结果:
js
const fs = require("fs");
fs.readFile("./1.txt", "utf8", function(err, data) {
console.log(err, data);
});
2. 事件和回调函数
我们使用Node的api会发现,我们会使用到大量的事件监听和回调函数,比如我们利用可读流
去读取input.txt
文件,我们需要监听可读流
的data事件
,在时间会调用拿到读取结果:
js
const fs = require('fs');
const readableStream = fs.createReadStream('input.txt');
readableStream.on('data', (data) => {
console.log(data.toString())
});
3. 单线程
这里只是说Node的主线程是单线程的,Node其实是可以通过child_process
模块创建多线程去执行任务的。
3.1 单线程的好处:
- 不用在意状态的同步问题,没有死锁。
- 没有线程上下文切换的开销。
3.2 单线程的缺点:
- 无法利用多核CPU
- 一旦出现错误会引起整个应用退出,对应用的健壮性要求高
- 大量计算占用CPU导致无法继续调用异步I/O
而对于大量计算的场景,浏览器端可以使用Web Workers
。Web Workers能够创建工作线程来进行计算,以解决JavaScript大计算阻塞UI渲染的问题,而在Node端,可以利用我们上面提高的Node内置模块child_process
创建多线程。
4. 跨平台
在Node架构层面,在操作系统与Node上层模块系统之间构建了一层平台层架构libuv,实现Windows和linux平台的兼容。
Node的应用场景
- I/O密集型
- 分布式应用
不适用的场景:CPU密集型,比如大量计算
小结
今天简单了解下Node,知道了为啥选择javascript
来实现node,然后了解了node的四大特点异步I/O
、事件和回调函数
、单线程
、跨平台
,最后简单了解了node的应用场景,算是对node的一个简单邂逅吧!