node fs 模块优雅的调用方式
前提
为了验证本文代码的真实性,我们可以提前创建好环境
打开你的 terminal,运行下面的命令(macOS 系统)
mkdir nodeFs & cd nodeFs
npm init
touch artical.txt
touch test.js
ls
然后你应该能看到这样的文件结构
├── nodeFs
│ ├── test.js
│ ├── package.json
│ ├── artical.txt
打开 artical.txt,写入一些文字 “this is a artical file, you can write some words here.”
准备工作就完成了,下面进入正题,介绍一下如何优雅的调用 fs 的方法
一、利用回调
标准的 fs 模块的使用,需要利用回调函数,代码如下:
// test.js
const fs = require("fs")
// 异步读取
fs.readFile('artical.txt', function (err, data) {
if (err) {
return console.error(err);
}
console.log("异步读取: " + data);
});
// 同步读取
const data = fs.readFileSync('artical.txt');
console.log("同步读取: " + data);
使用 node test.js
命令来执行 test 文件,结果正是我们期待的:
异步读取: this is a artical file, you can write some words here
同步读取: this is a artical file, you can write some words here
二、封装 promise
很显然,我们更习惯使用异步方式来实现逻辑,但是在上面的异步中,我们无法将回调函数中的结果(data)抛给外面
通常为了解决这个问题,我们需要手动在外面包上一层 promise,如下:
// test.js
const fs = require("fs")
function readFile(filePath) {
return new Promise((resolve, reject) => {
fs.readFile(filePath, (err, data) => {
if (err) {
reject(err);
}
resolve(data.toString());
})
})
}
// 调用方式一:
readFile('artical.txt').then(data => {
console.log("结果1: " + data)
})
// 调用方式二:
(async () => {
const data = await readFile('artical.txt')
console.log("结果2: " + data)
})()
使用 node test.js
命令来执行 test 文件,结果依然是我们想的那样:
结果1: this is a artical file, you can write some words here
结果2: this is a artical file, you can write some words here
三、借助 node util
当然,node也提供了一类工具,可以非常优雅的帮助你实现上面的方法
// test.js
const util = require('util')
const fs = require('fs')
const readFile = (fileName) => util.promisify(fs.readFile)(fileName, 'utf8');
(async () => {
const data = await readFile('artical.txt')
console.log(data)
})()
使用 node test.js
命令来执行 test 文件,不出所料:
this is a artical file, you can write some words here
四、实验 API
10.X版本的 node 提供了 promises 来取代回调函数,这是更优雅的实现方式
const { promises: { readFile } } = require('fs');
(async () => {
const data = await readFile('artical.txt', 'utf8')
console.log(data)
})()
使用 node test.js
命令来执行 test 文件,你会看到一个提示,告诉你 fs.promises API 是实验性的,但是你完全不必担心,可以放心的使用
(node:16392) ExperimentalWarning: The fs.promises API is experimental
this is a artical file, you can write some words here
当然,不仅仅是读取文件,fs 的其他方法,都可以这样子引入
const { promises: { readFile, writeFile, unlink, access } } = require('fs');
显然,这样很符合我们的按需引入原则,如果你觉得麻烦,你也可以像下面这样引入
// test.js
const fs = require('fs').promises;
(async () => {
const data = await fs.readFile('artical.txt','utf8')
console.log(data)
})()
结果依然可以预期:
(node:16392) ExperimentalWarning: The fs.promises API is experimental
this is a artical file, you can write some words here
tips:在使用promise的时候,读取的文件默认是返回 buffer类型,如果不想要buffer,需要在读取的时候指定方式为 utf8
,或者手动调用 buffer.toString()
5、demo1
下面来实现一个判断文件是否存在,存在就删除该文件的小 demo
// test.js
const { promises: { unlink, access } } = require('fs');
(async () => {
let exited = true, filePath = 'artical.txt'
try {
await access(filePath)
} catch (e) {
exited = false
}
if (exited)
await unlink(filePath)
})()
打开 terminal,运行:
node test.js
ls
此时,应该能够看到,artical.txt 被删除了
package.json test.js
6、demo2
下面我们通过 node 来重新生成 artical.txt
// test.js
const { promises: { writeFile, access } } = require('fs');
(async () => {
let exited = false,
filePath = 'artical.txt',
content = 'write some words in a new txt ';
try {
await access(filePath)
} catch (e) {
exited = true
}
if (exited)
await writeFile(filePath, content, 'utf8')
})()
再次运行:
node test.js
ls
此时,可以看到目录下有了 artical.txt 这个文件
artical.txt package.json test.js
通过 cat artical.txt
查看一下 artical.txt 的内容
write some words in a new txt
说明 artical.txt 这个文件正是我们通过 fs 的writeFile API 生成的
六、结束语
如果对你有帮助,请帮忙点个赞吧,感谢!