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 来取代回调函数,这是更优雅的实现方式

The fs.promises API provides an alternative set of asynchronous file system methods that return Promise objects rather than using callbacks. The API is accessible via require(‘fs’).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 生成的

六、结束语

如果对你有帮助,请帮忙点个赞吧,感谢!

猜你喜欢

转载自blog.csdn.net/zhai_865327/article/details/105104991