如何让fs.readFile回调内赋值的变量可在外部作用域正常使用
问题根源
你遇到的问题是fs.readFile是异步API,回调函数会在后续同步代码执行完成后才触发,所以你在回调外打印data、调用handlebars(data)的时候,读取文件的回调还没执行,data自然是undefined。
解决方案
下面给三种常用的可行方案,按需选择:
方案1:使用同步读取API(最简单,适合小体积配置文件)
直接把fs.readFile换成fs.readFileSync,同步读取文件会阻塞代码执行,直到读取完成再往下走,直接就能拿到结果:
function compileHandlebars() { options = { batch: ['./src/views/modules/*.hbs'] } // 同步读取文件,直接拿到结果 let data = fs.readFileSync('./data.json', 'utf-8'); console.log(data); // 可以正常输出内容 return gulp.src('./src/views/layouts/index.hbs') .pipe(handlebars(data)) .pipe(rename('index.html')) .pipe(gulp.dest('dist')); };
方案2:用async/await改写异步逻辑(符合现代JS写法,无阻塞)
直接用Node原生支持的Promise版本fs模块,用async/await控制执行顺序,保证读取完文件再执行后续gulp逻辑:
const fs = require('fs/promises'); async function compileHandlebars() { options = { batch: ['./src/views/modules/*.hbs'] } // 等待文件读取完成再往下执行 let data = await fs.readFile('./data.json', 'utf-8'); console.log(data); // 正常输出内容 return gulp.src('./src/views/layouts/index.hbs') .pipe(handlebars(data)) .pipe(rename('index.html')) .pipe(gulp.dest('dist')); };
方案3:把gulp逻辑放到回调内部(适配原有回调写法)
如果不想改原有API调用方式,可以把后续gulp执行逻辑放到readFile的回调里,保证拿到data之后再执行模板编译,注意要加done回调通知gulp任务执行完成:
function compileHandlebars(done) { options = { batch: ['./src/views/modules/*.hbs'] } fs.readFile('./data.json', 'utf-8', (error, content) => { if(error) throw error; let data = content; console.log(data); // 拿到数据后再执行gulp逻辑 gulp.src('./src/views/layouts/index.hbs') .pipe(handlebars(data)) .pipe(rename('index.html')) .pipe(gulp.dest('dist')) .on('end', done); }); };
内容的提问来源于stack exchange,提问作者Michał_Zagojski
相关产品推荐
相关产品推荐

