You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js中async调用fs.promises读写文件无报错不生效问题

问题根因

代码无反应的核心原因是混用了两套完全不兼容的Node.js fs异步API,且缺失错误捕获导致报错被静默吞掉:

  • 你引入的是fs.promises下的Promise风格文件方法,这类方法不接收回调函数作为入参,只会返回Promise对象,你传入的read回调永远不会被触发,内部的读写逻辑自然不会执行
  • Promise风格API抛出的异常(比如文件不存在、权限不足、文件被占用)必须通过try/catch或者.catch()捕获,你没有写错误处理,所有报错都被静默吞掉,从外部看就像程序完全没反应
  • 额外的逻辑错误:
    • 回调内的content变量没有声明,属于隐式全局变量,严格模式下会直接抛错
    • 写文件时传入数字类型的content,fs会将数字识别为字节长度参数,不会写入你预期的文本内容
    • 你在readFile后立刻又调用了一次writeFile写'test',哪怕回调逻辑能正常执行,两个写操作也会产生竞态冲突,反而会导致文件内容错乱
正确写法

首先是单调用场景下符合Promise异步规范的基础写法:

const fs = require('fs').promises;
async function stater(amount){
  try {
    // 读文件指定utf8编码直接拿到字符串内容,不需要传回调
    const data = await fs.readFile('stater.txt', 'utf8');
    let content = Number(data);
    content += Number(amount);
    if(amount === "clear") content = 0;
    // 写入时要把数字转成字符串,等写入完成后再打日志
    await fs.writeFile('stater.txt', String(content));
    logger.trace("Stater added: " + amount);
  } catch (err) {
    // 首次运行文件不存在时自动初始化
    if (err.code === 'ENOENT') {
      const initVal = amount === "clear" ? '0' : String(amount);
      await fs.writeFile('stater.txt', initVal);
      return;
    }
    throw err;
  }
}
stater(10000);

如果你需要支持每秒多次高频调用,光用上面的写法还会出现竞态问题:多个调用同时进入时会同时读到旧的文件值,计算后互相覆盖写入,最终数值不准。需要加一个简单的串行锁保证所有读写操作按顺序执行:

const fs = require('fs').promises;
// 串行执行锁,保证所有stater调用按顺序排队执行
let staterTask = Promise.resolve();
async function stater(amount){
  staterTask = staterTask.then(async () => {
    let content = 0;
    try {
      const data = await fs.readFile('stater.txt', 'utf8');
      content = Number(data);
    } catch (err) {
      if (err.code !== 'ENOENT') throw err;
    }
    content += Number(amount);
    if(amount === "clear") content = 0;
    await fs.writeFile('stater.txt', String(content));
    logger.trace("Stater added: " + amount);
  });
  return staterTask;
}

// 短时间高频调用也不会出现写覆盖问题
stater(10000);
stater(200);
stater(50);

内容的提问来源于stack exchange,提问作者mkrdev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 11:06:23