Node.js中await未等待fs.readdir执行完成导致数组为空问题
问题根因
你的await没生效的核心问题出在这两点:
async关键字不会自动等待函数内部的所有异步操作,只有当函数内部返回Promise、或者await了Promise对象时,外部的await才会等对应异步逻辑执行完再往下走。- 你用的
fs.readdir是回调风格的异步API,调用后会立刻把回调逻辑塞进事件队列,函数本身直接同步执行完,返回一个resolve值为undefined的Promise。等外部await判定执行完成、开始打印数组的时候,读目录的回调还没触发,filesToMove自然是空的。
修复方法
两种常用实现,按需选就行:
方法1:直接用fs的Promise版API
Node.js 10及以上版本自带fs/promises模块,所有API都返回Promise,直接配合await写就不会有等待问题:
// 注意引入promise版本的fs模块 const fs = require('fs/promises'); let filesToMove = []; async function readFiles() { const testFolder = "./files_to_move/"; const files = await fs.readdir(testFolder); files.forEach(file => { filesToMove.push(file); console.log("done"); }); } async function printFiles() { await readFiles(); console.log(filesToMove.length); filesToMove.forEach(item => console.log(item)); } // 不要忘记调用入口函数 printFiles().catch(err => console.error('执行出错:', err));
更推荐的写法是不要用全局数组存文件列表,直接在readFiles里把拿到的files返回,外部用const files = await readFiles()接收就行,能避免全局变量带来的状态混乱。
方法2:手动包装回调为Promise
如果是低版本Node环境用不了fs/promises,可以自己把回调逻辑包成Promise:
const fs = require('fs'); let filesToMove = []; async function readFiles() { const testFolder = "./files_to_move/"; return new Promise((resolve, reject) => { fs.readdir(testFolder, (err, files) => { if (err) { reject(err); return; } files.forEach(file => { filesToMove.push(file); console.log("done"); }); resolve(); }); }); } async function printFiles() { await readFiles(); console.log(filesToMove.length); filesToMove.forEach(item => console.log(item)); } printFiles().catch(err => console.error('执行出错:', err));
补充:所有异步IO操作都要加错误捕获,不然遇到目录不存在、权限不够的情况,程序会直接抛出未捕获异常崩溃。
内容的提问来源于stack exchange,提问作者Bar
相关产品推荐
相关产品推荐

