2017-04-18 50 views
0

我有一个奇怪的问题,当我提交表单时,它重定向到表单动作URL,然后显示空白页面。当我重新加载它时,它将显示数据。node js post request只能第二次使用

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/runcommand

延伸布局

block content 
    h1= "Result" 
    pre= data 

当我提交的形式,它会重定向到http://172.18.0.60:3000/runcommand只显示H1,当我再次重新加载它,它显示数据

它为什么表现如此呢?

回答

4

exec()是异步的,因此它会在您拨打res.render()后完成。所以,只有在所有exec()调用都完成后,您才需要渲染。如果您使用promises和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中的其他值产生影响。像这样的累计数据需要位于请求处理程序中的局部变量中或请求对象中的属性中,以便它永远不会与正在处理的其他请求冲突。

+0

太棒了!说明。 –