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

Express调用Node脚本demo.js时无法创建result.json文件的问题

问题分析与解决

问题场景

我搭建了一个Express服务器,流程如下:

  • 接收POST请求的JSON数据,写入./solver/src/test.json文件
  • 通过childProcess.fork调用demo.js脚本
  • demo.js读取test.json完成计算后,写入result.json
  • 服务器读取result.json并返回给客户端

遇到的问题:直接在终端执行node demo.js时,能正常生成result.json;但通过Express服务器调用脚本时,脚本能正常执行(可打印计算结果),却无法生成result.json,导致服务器因找不到文件抛出异常。

相关代码

Express服务器代码

// Function that runs the demo.js script
function runScript(scriptPath, callback) {
    // keeps track of whether callback has been invoked to prevent multiple invocations
    var invoked = false;

    var process = childProcess.fork(scriptPath);

    // listen for errors as they may prevent the exit event from firing
    process.on('error', function (err) {
        if (invoked) return;
        invoked = true;
        callback(err);
    });

    // execute the callback once the process has finished running
    process.on('exit', function (code) {
        if (invoked) return;
        invoked = true;
        var err = code === 0 ? null : new Error('exit code ' + code);
        callback(err);
    });
}

app.post('/', (req, res) => { 
    console.log("Received");

    fs.writeFile('./solver/src/test.json', JSON.stringify(req.body) , err => {
        if(err){
            console.error(err);
        }
    });

    runScript('./solver/src/demo.js', function (err) {
        if (!err){
            fs.readFile('./solver/src/result.json', (err, data) => {
                if(err) throw err;
                const jsonResp = JSON.stringify(data);
                res.send(data);
                console.log('finished running some-script.js');
            });
        } else {
            console.error(err);
        }
    });
});

demo.js代码

// result is a string generated by previous instructions 
// contained in the demo.js file, it gets correctly 
// printed by the console.log at the end of the script

fs.writeFile('./result.json', JSON.stringify(result) , (err) => { 
    if(err){ console.error(err); } 
    else{ console.log("File created succesfully"); } 
}); 
console.log(JSON.stringify(result, null, 1));

问题原因

  1. 工作目录不一致:终端直接运行demo.js时,工作目录是脚本所在的./solver/src/;但Express调用childProcess.fork时,子进程的工作目录是服务器的启动目录,而非demo.js所在目录。因此./result.json会被写入服务器启动目录,而非预期的./solver/src/,导致服务器找不到文件。
  2. 异步操作未等待:fs.writeFile是异步操作,可能在test.json未完全写入时就启动了demo.js,不过从现象看,这不是主要问题,但会引发潜在的读取异常。

修复方案

方案1:指定子进程工作目录

修改runScript函数中的fork调用,添加cwd参数,将子进程工作目录设置为demo.js所在目录:

// 先引入path模块
const path = require('path');

function runScript(scriptPath, callback) {
    var invoked = false;
    // 设置子进程工作目录为脚本所在路径
    var process = childProcess.fork(scriptPath, {
        cwd: path.dirname(scriptPath)
    });

    // 后续监听逻辑不变...
}

方案2:等待文件写入完成后再启动脚本

修改POST路由,确保test.json写入完成后再调用demo.js,避免读取未完成的文件:

app.post('/', (req, res) => { 
    console.log("Received");

    fs.writeFile('./solver/src/test.json', JSON.stringify(req.body) , err => {
        if(err){
            console.error(err);
            return res.status(500).send('写入test.json失败');
        }
        // 等待文件写入完成后再启动脚本
        runScript('./solver/src/demo.js', function (err) {
            if (!err){
                fs.readFile('./solver/src/result.json', (err, data) => {
                    if(err) {
                        console.error(err);
                        return res.status(500).send('读取result.json失败');
                    }
                    res.send(data);
                    console.log('finished running demo.js');
                });
            } else {
                console.error(err);
                res.status(500).send('执行demo.js失败');
            }
        });
    });
});

方案3:在demo.js中使用绝对路径

修改demo.js,用__dirname拼接文件路径,确保写入到脚本所在目录:

const path = require('path');

// ... 其他计算逻辑

fs.writeFile(path.join(__dirname, 'result.json'), JSON.stringify(result) , (err) => { 
    if(err){ console.error(err); } 
    else{ console.log("File created succesfully"); } 
}); 
console.log(JSON.stringify(result, null, 1));

注意事项

  • 优先使用方案1+方案2,既保证工作目录正确,又避免异步操作的时序问题。
  • 处理文件读写错误时,不要直接抛出异常,应返回客户端对应的错误响应,避免服务器崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 10:17:53