Node中有很多内置模块,这些模块可以很方便地对文件,网络进行操作。有path,http,fs等等模块。我们来看一下详细的看一下。
Path模块
- 路径的拼接:
const path = require('path')
const basePath = '/User/zengge'
const filename = 'foo.js'
const filePath = path.resolve(basePath, filename)
console.log(filePath)
因为再window、macos、linux操作系统上的文件路径是不一样的,所以有时候路径的显示会有一些问题,所以我们推荐使用path.resolve()拼接路径名。
- 获取路径的信息
const filePath = '/User/zengge/foo.js'
console.log(path.dirname(filePath)) // 获取路径中的目录部分
console.log(path.basename(filePath)) // 获取路径的文件名,默认包含扩展名
console.log(path.extname(filePath)) // 获取一个路径中的扩展名部分
console.log(path.join('c:/a','/b','/c.js')) // 路径拼接
path.resolve和path.join都是拼接路径,它们的区别就是path.join只是单纯地拼接,而path.resolve是把'/'当成根目录。
fs模块
fs的API非常多,下面介绍几个常用的API:
- fs.statSync(filePath) 同步获取文件的状态
const fs = require('fs')
const filePath = './foo.txt'
const info = fs.statSync(filePath) // 同步操作 会阻塞后续的代码
console.log('后续需要执行的文件')
console.log(info)
- fs.stat(filePath, callBack) 异步获取文件的状态
const fs = require('fs')
const filePath = './foo.txt'
fs.stat(filepath, (info,err) => {
if(err) {
console.log(err)
return
}
console.log(info)
}) // 异步操作 不会阻塞后面的代码
console.log('后续需要执行的文件')
这种方法有一个很明显的缺点,会产生回调地狱,所以还有一种方法就是Promise的方式来使用它
- fs.promise.stat(filePath)
promise获取文件的状态
const fs = require('fs')
const filePath = './foo.txt'
fs.promise.stat(filepath).then((res)=>{
console.log(res)
}).catch((err)=>{
console.log(err)
})
- fs.open(path[, flags[, mode]], callback) 文件描述符
const fs = require('fs')
const filePath = './foo.txt'
fs.open(filePath, () => {
if(err) {
console.log(err)
return
}
// 通过描述符去获取文件的信息
fs.fstat(fd, (err, info) => {
console.log(info)
})
})
- fs.writeFile(filePath, content, [option], callBack) 异步写入文件
const fs = require('fs')
const filepath = './demo.txt'
fs.writeFile(filepath, 'hello world', err => {
if (err) {
console.log(err)
} else {
console.log('写入成功')
}
})
这个是基本的使用方法,我们还有其实还可以使用flag选项进行其他配置:
w打开文件写入,默认值w+打开文件进行读写,如果不存在则创建文件r+打开文件读写,如果不存在则抛出异常r打开文件读取,读取时的默认值a打开要写入的文件,将流放在文件末尾。如果不存在则创建文件a+打开文件以进行读写,将流放在文件末尾。如果不存在则创建文件
const fs = require('fs')
const filepath = './demo.txt'
fs.writeFile(filepath, 'hello world', {flag: 'a'},err => {
if (err) {
console.log(err)
} else {
console.log('写入成功')
}
})
- fs.readFile(filePath, [option], callBack) 异步读取文件
const fs = require('fs')
const filepath = './demo.txt'
fs.readFile(filepath, {encoding: 'utf-8'},(err, data) => {
if (err) {
console.log(err)
} else {
console.log(data)
}
})
文件操作演练
const fs = require('fs')
// 创建文件夹
const dirname = './zengge'
if(!fs.existSync(dirname)){
fs.mkdir(dirname, err => {
console.log(err)
})
}
// 读取文件夹中的文件(递归)
function getFiles(dirname) {
fs.readdir(dirname, {withFileTypes: true}, (err, files) => {
files.forEach((file)=>{
if(file.isDirectory()){
const filepath = path.resolve(dirname, file.name)
getFiles(filepath)
}else{
console.log(file.name)
}
})
})
}
getFiles(dirname)
// 文件夹的重命名
fs.rename('./zengge', './zengdada', (err, data) => {
console.log(data)
})
event模块
Events 模块是Node最重要的模块,它提供了一个属性 EventEmitter,EventEmitter 的核心是事件发射与事件监听器
Node中大部分的模块,都继承自 Events 模块。
Events模块是Node对 发布订阅模式(publish/subscribe)的实现。一个对象通过这个模块,向另一个对象传递消息。- 该模块通过
EventEmitter属性,提供了一个构造函数。该构造函数的实例具有on方法,可以用来监听指定事件,并触发回调函数。 - 任意对象都可以发布指定事件,被
EventEmitter实例的on方法监听到。 关于Events中的发布订阅模式,我们要先清楚它的几个常用方法。 - 订阅方法:
on方法用来订阅事件,订阅是将方法对应成一种一对多的关系。 - 发布方法:
emit用来执行订阅的事件。 - 取消订阅:
off方法可以移除对应的事件监听。 - 订阅一次:
once绑定事件当执行后自动删除订阅的事件。
const EventEmitter = require('events')
// 创建发射器
const emitter = new EventEmitter()
// 监听某一事件
emitter.on('click', (args) => {
console.log('监听到click事件', args)
})
// 发出事件
emitter.emit('click', 'zengge', 'zengdada')