一、path模块
定义:
path
模块用于对路径和文件进行处理,提供了很多好用的方法。
1、从路径中获取信息
-
dirname:
获取文件的父文件夹; -
basename:
获取文件名; -
extname:
获取文件扩展名;
路径的拼接 (path.join
函数 ):如果我们希望将多个路径进行拼接,但是不同的操作系统可能使用的是不同的分隔符;
2、将文件和某个文件夹拼接
- 如果我们希望将某个文件和文件夹拼接,可以使用
path.resolve
-
resolve
函数会判断我们拼接的路径前面是否有 / 或 ../ 或 ./ ; - 如果有表示是一个绝对路径,会返回对应的拼接路径;
- 如果没有,那么会和当前执行文件所在的文件夹进行路径的拼接
二、fs模块
定义:fs是File System的缩写,表示文件系统
1、这些API大多数都提供三种操作方式:
方式一:同步操作文件:代码会被阻塞,不会继续执行;
方式二:异步回调函数操作文件:代码不会被阻塞,需要传入回调函数,当获取到结果时,回调函数被执行;
方式三:异步Promise操作文件:代码不会被阻塞,通过
fs.promises
调用方法操作,会返回一个Promise, 可以通过then、catch进行处理;
获取一个文件的状态:
const fs = require("fs");
const filepath = "./abc.txt";
// 1.方式一:
const state = fs.statSync(filepath);
console.log(state);
console.log("后续的代码");
// 2.方式二:
fs.stat(filepath, (err, state) => {
if (err) {
console.log(err);
return;
}
console.log(state);
});
console.log("后续的代码");
// 3.方式三:
fs.promises
.stat(filepath)
.then((state) => {
console.log(state);
})
.catch((err) => {
console.log(err);
});
console.log("后续的代码");
2、文件描述符
文件描述符(File descriptors)是什么呢?
- 在 POSIX 系统上,对于每个进程,内核都维护着一张当前打开着的文件和资源的表格。
- 每个打开的文件都分配了一个称为文件描述符的简单的数字标识符。
- 在系统层,所有文件系统操作都使用这些文件描述符来标识和跟踪每个特定的文件。
- Windows 系统使用了一个虽然不同但概念上类似的机制来跟踪资源。
通过文件描述符去获取文件信息: fs.open()
方法用于分配新的文件描述符。 一旦被分配,则文件描述符可用于从文件读取数据、向文件写入数据、或请求关于文件的信息。
const fs = require('fs')
fs.open('./abc.txt', (err, fd) => {
if (err) {
console.log(err);
return
}
// 通过文件描述符去获取文件信息
fs.fstat(fd, (err, info) => {
console.log(info);
})
})
3、文件的读写
对文件的内容进行操作,这个时候可以使用文件的读写:
-
fs.readFile(path[, options], callback)
:读取文件的内容; -
fs.writeFile(file, data[, options], callback)
:在文件中写入内容;
option参数:
flag:写入的方式
encoding:字符的编码
文件写入:
const fs = require('fs')
const content = '你好啊, kk'
fs.writeFile('./abc.txt', content, {flag: 'a'}, err => {
console.log(err);
})
文件读取:
如果不填写encoding,返回的结果是Buffer
4、文件夹的操作
新建文件夹
const fs = require('fs')
const path = require('path')
const dirname = './zyk'
// 1.新建文件夹
if (!fs.existsSync(dirname)) {
fs.mkdir(dirname, (err) => {
console.log(err);
})
}
获取文件夹的内容
// 2.获取文件夹里的内容
// fs.readdir(dirname, (err, files) => {
// console.log(files);
// })
function getFiles(dirname) {
fs.readdir(dirname, {withFileTypes: true} ,(err, files) => {
files.forEach(file => {
// 判断是否为目录
if (file.isDirectory()) {
const newFolder = path.resolve(dirname, file.name)
getFiles(newFolder)
} else {
console.log(file.name);
}
})
})
}
getFiles(dirname)
文件夹重命名
// 3.文件夹重命名
fs.rename(dirname, './ks', err => {
console.log(err);
})
三、events内置模块
Node中的核心API都是基于异步事件驱动的:
- 在这个体系中,某些对象(发射器(Emitters))发出某一个事件;
- 我们可以监听这个事件(监听器 Listeners),并且传入的回 调函数,这个回调函数会在监听到事件时调用;
发出事件和监听事件都是通过EventEmitter类来完成的,它们都属 于events对象。
-
emitter.on(eventName, listener)
:监听事件,也可以使用addListener
; -
emitter.off(eventName, listener)
:移除事件监听,也可以使 用removeListener
; -
emitter.emit(eventName[, ...args])
:发出事件,可以携带一 些参数;
const EventEmmiter = require('events')
const emmiter = new EventEmmiter()
// 监听事件
const listener1 = (...args) => {
console.log('监听1到click事件', ...args);
}
emmiter.on('click', listener1)
const listener2 = (...args) => {
console.log('监听2到click事件', ...args);
}
emmiter.on('click', listener2)
// 发送事件
setTimeout(() => {
emmiter.emit('click', "kk", "ss")
// 取消监听事件
emmiter.off('click', listener2)
emmiter.emit('click', "kk", "ss")
}, 2000)
四、http模块
1、创建服务器
创建服务器对象,我们是通过 createServer 来完成的
-
http.createServer
会返回服务器的对象; - 底层其实使用直接
new Server
对象。
const http = require('http')
// 创建一个web服务器
// 方式一:
const server = http.createServer((req, res) => {
res.end('hello kk')
})
server.listen(8888, '0.0.0.0', () => {
console.log('服务器启动成功~');
})
自己来创建这个对象:
// 方式二:
const server1 = new http.Server((req, res) => {
res.end('hello ss')
})
server1.listen(8889, '0.0.0.0', () => {
console.log('服务器启动成功~');
})
2、监听主机和端口号
Server
通过listen
方法来开启服务器,并且在某一个主机和端口上监听网络请求, 也就是当我们通过ip:port
的方式发送到我们监听的Web服务器上时, 我们就可以对其进行相关的处理;
listen函数有三个参数:
(1)端口port: 可以不传, 系统会默认分配端
(2)主机host: 通常可以传入localhost、ip地址127.0.0.1、或者ip地址0.0.0.0,默认是0.0.0.0;
- localhost:本质上是一个域名,通常情况下会被解析成127.0.0.1;
- 127.0.0.1:回环地址(Loop Back Address),表达的意思其实是我们主机自己发出去的包,直接被自己接收;
- 0.0.0.0:监听IPV4上所有的地址,再根据端口找到不同的应用程序;
(3)回调函数:服务器启动成功时的回调函数;
3、request对象-url
客户端在发送请求时,会请求不同的数据,那么会传入不同的请求地址:
- 本次请求的URL,服务器需要根据不同的URL进行不同的处理;
- 本次请求的请求方式,比如GET、POST请求传入的参数和处理的方式是不同的;
- 本次请求的headers中也会携带一些信息,比如客户端信息、接受数据的格式、支持的编码格式等;
这些信息,Node会帮助我们封装到一个request的对象中,我们可以直接来处理这个request对象:
const http = require('http')
const server = http.createServer((req, res) => {
console.log(req.url);
console.log(req.method);
console.log(req.headers);
res.end('hello kk')
})
server.listen(8000, '0.0.0.0', () => {
console.log('服务器启动成功~');
})
4、request对象-method
在Restful规范(设计风格)中,我们对于数据的增删改查应该通过不同的请求方式:
- GET:查询数据;
- POST:新建数据;
- PATCH:更新数据;
- DELETE:删除数据;
5、headers属性
在request对象的header中也包含很多有用的信息,客户端会默认传递过来一些信息
content-type:是这次请求携带的数据的类型
-
application/json
表示是一个json类型; -
text/plain
表示是文本类型; -
application/xml
表示是xml类型; -
multipart/form-data
表示是上传文件;
content-length:文件的大小和长度
keep-alive:
(1)http是基于TCP协议的,但是通常在进行一次请求和响应结束后会立刻中断;
(2)在http1.0中,如果想要继续保持连接:
- 浏览器需要在请求头中添加 connection: keep-alive;
- 服务器需要在响应头中添加 connection:keey-alive;
- 当客户端再次放请求时,就会使用同一个连接,直接一方中断连接;
(3)在http1.1中,所有连接默认是 connection: keep-alive的;
- 不同的Web服务器会有不同的保持 keep-alive的时间;
- Node中默认是5s中;
accept-encoding: 告知服务器,客户端支持的文件压缩格式,比如js文件可以使用gzip编码,对应 .gz文件;
accept: 告知服务器,客户端可接受文件的格式类型;
user-agent: 客户端相关的信息;
6、返回响应结果
如果我们希望给客户端响应的结果数据,可以通过两种方式:
- Write方法:这种方式是直接写出数据,但是并没有关闭流;
- end方法:这种方式是写出最后的数据,并且写出后会关闭流;
如果我们没有调用 end和close,客户端将会一直等待结果:所以客户端在发送网络请求时,都会设置超时时间。
7、常见的状态码
设置状态码常见的有两种方式:
8、响应头文件
返回头部信息,主要有两种方式:
-
res.setHeader:
一次写入一个头部信息; -
res.writeHead:
同时写入header和status;