这是我参与「第五届青训营」伴学笔记创作活动的第 7 天,欢迎各位大佬批评指正。
Node 概述
Node.js 应用场景
node.js是基于V8引擎的ECMAScript运行时环境,可以执行js文件,并且提供大量API,使得能快速完成文件读写,web服务器创建等,大大拓展了js的应用领域(可以像java和python一样完成一些后端/服务端的能力)。具体的应用可以细分如下:
- 前端工程化
前端工程化越来越成为目前前端标准化开发的主流模式,比如:
- Budler:
webpack、vite、esbuild、parcel... - Transpile:
babeljs、typescript... - Uglify:
uglifyjs - 其他语言加入:
esbuild (go)、parcel (rust)、prisma (新一代ORM)...
- Web服务端应用
- 学习曲线平缓,运行效率接近常见的编程语言。
- 社区生态丰富,工具链成熟(npm、V8 inspector等)。
- 与前端结合的场景有较大优势(SSR等)。
- Electron跨端桌面应用
- 依赖Electron开发的商业应用:
vscode、slack、discord、zoom... - 大型公司内的效率工具...
💡node.js的出现不仅使得js不仅仅运行在浏览器环境,也可以运行在桌面、服务器等,极大拓展了js语言的活力,npm上过百万的包也展示了这项工具的生命力;前端的开发者摆脱了过去只能调用后端接口的尴尬局面,通过node.js可以简单写出一个web服务器应用,也可以通过工程化工具等,轻松实现跨端,前端开发的范围也越来越广~
Node.js 运行时结构
-
异步I/O
I/O即Input/Output,当处理器访问内存、磁盘、显卡等外部设备时,都可以当作I/O操作。
Node.js作为单线程的模式,任务是顺序执行的,一旦有任务执行时间过长,会影响后续任务的执行。为了解决这个问题,Node.js采用了异步I/O模式,更合理得利用资源,提高程序运行效率。 -
事件循环机制
对于异步I/O解决方式,就不得不提到
Node.js中事件循环。和浏览器的事件循环有些许不同,不再分为宏任务、微任务,而是在由以下步骤组成:
- timers:这个阶段执行
setTimeout和setInterval指定的回调函数。 - I/O:此阶段执行上一次未完的系统的回调函数(即除了timers和close callback的全部回调)。
- idle, prepare:空转,仅在
node内部调用。 - poll:轮询。首先同步执行队列中到期的I/O回调函数,执行结束判断是否有timers或
setImmediate回调到期,无则I/O阻塞等待,有则跳转执行。 - check:这个阶段用于执行
setImmediate指定的回调。
如果poll队列任务执行结束后,如果有设置
setImmediate,则会立即跳转check阶段,如果没有则阻塞等待,如果poll队列为空并且没有到期的setImmediate同时setTimeout或setInterval到期,则立即跳转到timers执行。
Node.js 内置模块
文件模块
文件模块,即fs模块,是node中内置的一个模块,能够用于创建/删除文件,读写系统文件,获取文件详情等。通过require命令引入。
const fs = require('fs');
1. 读/写文件命令
- 读取文件内容:
path为文件路径;options可选,表示以何种编码模式解析文档;callback接受两个参数(err, datastr)。
fs.readFile('path', ['options'], callback)
fs.readFileSync('path', ['options'])
- 写入内容
fs.writeFile('path', datastr, ['options'], callback)
fs.writeFileSync('path', datastr, ['options'])
- 追加文件内容
fs.appendFile('path', datastr, ['options'], callback)
fs.appendFileSync('path', datastr, ['options'])
2. 创建/删除/遍历文件
- 查看文件状态
fs.stat('path', callback) //异步
fs.statSync('path') //同步
- 判断是否为文件
fs.isFile('path')
- 判断是否为目录
fs.isDirectory('path')
- 删除文件
fs.unlink('path', callback)
fs.unlinkSync('path')
- 创建目录
fs.mkdir('path', callback)
- 读取目录
fs.readdir('path', callback)
- 重命名
fs.rename('path', 'newname', callback)
- 删除目录
fs.rmdir('path', callback)
注:后缀为Sync即同步操作,没有callback;否则为异步,一定有callback。
路径模块
由于涉及到系统中文件读写,因此路径非常重要。node也提供了内置的模块帮助快速写出准确的路径:
const path = require('path');
//拼接路径
path.join('path1', 'path2', ...);
//获取路径最后的信息;如果加上后缀(第二个参数),只返回文件名
path.basename('path', ['suffix']);
//获取路径中扩展名部分
path.extname('path')
//当前执行文件所在目录
__dirname;
http 模块
内置模块,可用于快速搭建一个简单的web应用:
const http = require('http');
const sever = http.creatSever();
//给sever绑定请求事件响应
sever.on('request', (req, res) => {
//业务代码
console.log('request has been received');
return true;
}
//启动服务器
sever.listen(port, callback)
Node.js 编写 http-sever
基于node有很多开源框架可以快速搭建一个较为完备的web框架,比如:express、koa等。下面以express为例简单搭建一个http-sever:
npm安装express包
npm i express
- 创建基本web服务器
const express = require('express');
const app = express();
app.listen(80, () => {
console.log('http has been started');
}
- 监听GET请求
app.get('url', callback);
- 监听POST请求
app.post('url', callback);
- 托管静态资源
//创建静态资源服务器
const libstatic = express.static('path');
//挂载到web服务器上对外访问
app.use(libstatic)
至此,一个最简单的基于express的web应用就搭建完成啦~