node.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > node.js > Node.js fs读写文件

Node.js中fs模块读写文件的四种方案全解析

作者:mONESY

fs 是 Node 内置文件系统模块,用于读写文件、操作文件夹,fs 提供了同步阻塞、回调异步、Promise、async/await 四种写法,下面小编就和大家详细讲讲吧

fs 是 Node 内置文件系统模块,用于读写文件、操作文件夹。JS 是单线程语言,fs 提供同步阻塞、回调异步、Promise、async/await 四种写法,一步步解决异步嵌套带来的回调地狱问题。

一、模块导入两种方式

基础 fs:提供同步 API、回调风格异步 API

import fs from 'fs';

fs/promises:专门提供 Promise 风格 API,适配 async/await(推荐生产使用)

import fs from 'fs/promises';

二、方案 1:同步读取 readFileSync(阻塞主线程)

特点:代码顺序执行,文件读取期间阻塞整个线程,不适合接口、循环大量 IO;仅适合项目启动一次性读取配置文件。

import fs from 'fs';
const syncData = fs.readFileSync('./test.txt', 'utf-8');
console.log(syncData);

缺点:并发场景大量文件读写会严重降低服务性能。

三、方案 2:回调异步 readFile(ES6 原生写法,回调地狱)

Node 统一错误优先回调规范:(err, data) => {}

串行读取多个文件时会产生多层嵌套,即回调地狱,维护成本极高。

import fs from 'fs';
fs.readFile('./file1.txt', 'utf-8', (err, data) => {
  if (!err) {
    console.log('file1', data);
  } else {
    console.log(err);
  }
  fs.readFile('./file2.txt', 'utf-8', (err, data) => {
    if (!err) {
      console.log('file2', data);
    } else {
      console.log(err);
    }
    fs.readFile('./file3.txt', 'utf-8', (err, data) => {
      if (!err) {
        console.log('file3', data);
      } else {
        console.log(err);
      }
    })
  })
})

四、方案 3:Promise 链式调用(消除嵌套)

基于 fs/promises,readFile 返回 Promise,使用 .then() 链式串行执行,解决多层嵌套问题;缺点是多文件场景重复书写 then,代码冗余。

import fs from 'fs/promises';
fs.readFile('./file1.txt', 'utf-8')
  .then(data => {
    console.log('file1', data);
    return fs.readFile('./file2.txt', 'utf-8');
  })
  .then(data => {
    console.log('file2', data);
    return fs.readFile('./file3.txt', 'utf-8');
  })
  .then(data => {
    console.log('file3', data);
  })

五、方案 4:async/await(ES8 最优方案,生产首选)

async/await 是 Promise 的语法糖,底层依旧异步、不会阻塞主线程;代码线性自上而下书写,可读性最强。限制:await 只能写在 async 函数内,顶层直接 await 会报错,使用 IIFE 立即执行函数包裹。补充:Promise、await 属于微任务;setTimeout 属于宏任务。

import fs from 'fs/promises';
(async () => {
  const file1Data = await fs.readFile('./file1.txt', 'utf-8');
  console.log('file1', file1Data);
  const file2Data = await fs.readFile('./file2.txt', 'utf-8');
  console.log('file2', file2Data);
  const file3Data = await fs.readFile('./file3.txt', 'utf-8');
  console.log('file3', file3Data);
})();

完整健壮写法(增加 try/catch 捕获读取错误)

import fs from 'fs/promises';
(async () => {
  try {
    const data = await fs.readFile('./test.txt', 'utf-8');
    console.log(data);
  } catch (err) {
    console.error('文件读取失败:', err);
  }
})();

六、异步代码演进路线

同步阻塞(性能差)→ 回调函数(回调地狱)→ Promise then 链式(冗余)→ async/await(简洁易维护)

七、四种读取方式对比表

写法是否阻塞线程优点缺点
readFileSync阻塞写法极简大量 IO 严重影响服务性能
readFile 回调非阻塞无需额外导入串行多文件产生回调地狱
Promise then非阻塞无嵌套结构多文件链式代码重复繁琐
async await非阻塞线性阅读,代码整洁ES8 语法,需 async 函数包裹

八、工程开发最佳实践

  1. 业务文件读写统一使用 fs/promises + async/await
  2. 所有文件读取必须搭配 try/catch 捕获异常;
  3. 同步 readFileSync 仅用于项目初始化加载配置,接口业务禁止使用;
  4. 路径搭配 path.resolve 生成绝对路径,防止运行目录变更导致文件找不到。

到此这篇关于Node.js中fs模块读写文件的四种方案全解析的文章就介绍到这了,更多相关Node.js fs读写文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文