Javascript 节点js post请求只能第二次工作
我有一个奇怪的问题,当我提交表单时,它会重定向到表单操作URL,然后显示空白页面。当我再次重新加载它时,它将显示数据 index.jade-Javascript 节点js post请求只能第二次工作,javascript,node.js,express,command-line-interface,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
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 });
});
结果。jade-http://172.18.0.60:3000/runcommand
扩展布局
block content
h1= "Result"
pre= data
当我提交表单时,它将重定向到http://172.18.0.60:3000/runcommand
仅显示h1,当我再次重新加载它时,它会显示数据
为什么它会这样做?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
中践踏另一方的值。像这样的累积数据需要位于请求处理程序内部的局部变量中,或者位于请求对象的属性中,这样它就不会与处理中的其他请求冲突。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
中践踏另一方的值。像这样的累积数据需要存在于请求处理程序内部的局部变量中,或者存在于请求对象的属性中,这样它就不会与处理中的其他请求发生冲突。太好了!解释,太好了!解释。