【问题标题】:How to execute synchronously in nodejs?如何在nodejs中同步执行?
【发布时间】:2018-03-29 18:25:23
【问题描述】:

我有以下代码。

router.post('/',function(req, res, next) {
        var id=req.body.id;
        console.log(id);

    const testscript = exec('sh script.sh');

    testscript.stdout.on('data', function(data){
        console.log(data);
        // sendBackInfo();
    });

    testscript.stderr.on('data', function(data){
        console.log(data);
        // triggerErrorStuff();
    });

        res.redirect('/Visualise');
});

我需要完全执行我的 shell 脚本,然后重定向到“/Visualise”。下一页的部分代码使用了 shell 脚本生成的输出文件。它在完全执行 shell 脚本之前重定向,我收到一个文件未找到错误。 我怎样才能同步执行。请在上述代码中进行必要的更改以执行此操作。谢谢。

【问题讨论】:

  • res.redirect('/Visualise');移动到testscript.stdout.on
  • 请阅读副本并自行进行所需的更改:) 问题并非 100% 相同,但请阅读答案,您会发现适用的原则完全相同。
  • 你可以使用 Promise 或 await。

标签: javascript node.js express async-await


【解决方案1】:

您真正想要的不是同步执行脚本,因为这会阻塞事件循环并阻止其他请求运行。相反,您需要(异步)等待脚本完成。

为此,请将重定向写入子进程的 exit 事件中,而不是在处理程序的主体中:

router.post('/', function(req, res, next) {
    // ...whatever

    const testscript = exec('sh script.sh');

    // ...stdouts

    testscript.on('exit', function (code, signal) {
        res.redirect('/Visualise');
    });
});

【讨论】:

    【解决方案2】:

    您可以为此使用 child_process.execSync,它返回标准输出:

    child_process.execSync(command[, options])
    

    例如

    const child_process = require('child_process');
    var response = child_process.execSync('sh script.sh');
    

    响应将是一个 Buffer 对象。

    文档在这里:

    https://nodejs.org/api/child_process.html#child_process_child_process_execsync_command_options

    请注意,如果脚本超时或退出代码非零,此方法将抛出错误,因此您可能需要使用 try / catch 进行包装。

    要将其添加到您的代码中,请执行以下操作:

    const child_process = require('child_process');
    
    router.post('/',function(req, res, next) {
            var id=req.body.id;
            console.log(id);    
    
            try
            {
                var response = child_process.execSync('sh script.sh');
                console.log('Script response: ', response.toString());
            }
            catch (error) {
                console.error('An error occurred: ', error);
            }
    
            res.redirect('/Visualise');
    });
    

    更好的模式是异步执行此操作:

    const child_process = require('child_process');
    
    router.post('/',function(req, res, next) {
            var id=req.body.id;
            console.log(id);    
    
            child_process.exec('sh script.sh', (error, stdout) => {
                if (error) {
                    console.error(`exec error: ${error}`);
                    return;
                }
                console.log(`stdout: ${stdout}`);
    
                res.redirect('/Visualise');
            });
    });
    

    注意:切勿将未经处理的用户输入传递给此函数,这是一个很大的安全风险。

    【讨论】:

    • 在异步环境(例如 http 请求处理程序)中使用函数的同步版本从不是个好主意,因为它会阻塞主循环并阻止其他事件在通话期间不被处理。
    • @Darkhogg,我同意你的观点,我实际上对发布这个答案持谨慎态度,尽管这是 OP 所要求的。我会更新答案。
    猜你喜欢
    • 1970-01-01
    • 2018-07-29
    • 2019-09-24
    • 2018-07-09
    • 2017-11-14
    • 2018-07-24
    • 2017-12-26
    • 2019-04-21
    • 2018-09-01
    相关资源
    最近更新 更多