javascript - Node js post请求只能在第二次起作用

标签 javascript node.js express command-line-interface

我有一个奇怪的问题,当我提交表单时,它会重定向到表单操作 URL,然后显示空白页面。当我再次重新加载时,它将显示数据。

index.jade - http://172.18.0.60:3000/

  form#command(action='runcommand', method='post')
    input#cmdls(type='checkbox', name='cmdls', value='ls -la')
    label(for='cmdls') List Files
    br
    input#cmdpwd(type='checkbox', name='cmdpwd', value='pwd')
    label(for='cmdpwd') Print Working Directory
    br
    input#cmddate(type='checkbox', name='cmddate', value='date')
    label(for='cmddate') Date
    br
    input.button(type='submit', value='Run')

app.js

var tmp=""; 
app.post('/runcommand',function(req,res){

    for (var key in req.body) {

            console.log(key);
            function puts(error, stdout, stderr) { sys.puts(stdout) }
            exec(req.body[key], function(error, stdout, stderr) {
              if (!error) {
                    tmp+=stdout;                       
              } else {
                tmp+=stderr;
              }
            });

    }

    res.render("result",{ data: tmp });

});

result.jade - http://172.18.0.60:3000/runco​​mmand

扩展布局

block content
    h1= "Result"   
    pre=  data

当我提交表单时,它将重定向到http://172.18.0.60:3000/runco​​mmand,仅显示h1,当我再次重新加载时,它会显示数据

为什么会这样?

最佳答案

exec() 是异步的,因此它会在您调用 res.render() 后完成。因此,您只需要在所有 exec() 调用完成后才进行渲染。如果您使用 Promise 和 Promise.all() 来跟踪所有 exec() 调用何时完成,那么编码可能会更容易,但您也可以使用计数器来了解最后一个调用何时完成。

这是使用计数器的方案:

app.post('/runcommand', function(req, res) {

    let keys = Object.keys(req.body);
    let cnt = 0;
    let tmp = '';
    if (!keys.length) {
        // render something when there were no keys
        res.render(...)
    } else {
        keys.forEach(function(key) {
            console.log(key);

            exec(req.body[key], function(error, stdout, stderr) {
                if (!error) {
                    tmp += stdout;
                } else {
                    tmp += stderr;
                }
                ++cnt;
                // if all exec calls have finished, the render
                if (cnt === keys.length) {
                    res.render("result", {data:tmp});
                }
            });
        });
    }
});

附注这段代码看起来允许任何客户端在服务器上运行任何任意程序(如果它在路径中或者它们可以构造完整路径)。这看起来很危险。

P.P.S。像在原始代码中那样在处理程序外部累积 tmp 对于使用服务器的多个用户来说是一场灾难,因为多个请求可能会破坏 tmp 中任何一个的值。像这样的累积数据需要位于请求处理程序内的局部变量中,或者位于请求对象的属性中,以便它永远不会与处理中的其他请求发生冲突。

关于javascript - Node js post请求只能在第二次起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43465200/

相关文章:

javascript - Gulp 缩小所有 css/js 并移动到具有相同结构的文件夹?

javascript - Node.js 架构和应用程序结构

javascript - meteor /包的目的是什么?

javascript - 将键盘焦点设置为 YouTube 嵌入

javascript - 在 IE 上停止 BGSOUND 元素?

javascript - React Native 启动失败,错误代码 -4094 如何解决这个 ONCE for ALL?

javascript - 在使用 mocha 的测试脚本中从 webhook 接收通知事件

php - 尝试使用nodejs时没有输出

mongodb - 使用 ngrok 创建隧道连接到 MongoDB 本地数据库

node.js - Express-validator:我们如何验证对象键?