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

如何让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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 23:15:03