Tengo un problema extraño, cuando envío el formulario, se redirige a la URL de acción del formulario y luego muestra una página en blanco. Cuando lo vuelva a cargar, mostrará los datos.
índice.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')aplicación.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 }); }); resultado.jade - http://172.18.0.60:3000/runcommand
extiende el diseño
block content h1= "Result" pre= data Cuando envíe el formulario, se redirigirá a http://172.18.0.60:3000/runcommand solo mostrando h1, cuando lo vuelva a cargar, mostrará datos .
¿Por qué se comporta así?
exec() es asíncrono, por lo que finaliza DESPUÉS de llamar a res.render() . Por lo tanto, debe renderizar solo después de que hayan finalizado todas las llamadas exec() . Esto probablemente sería más fácil de codificar si usara promesas y Promise.all() para realizar un seguimiento de cuándo se realizaron todas las llamadas exec() , pero también podría usar un contador para saber cuándo se realizó la última.
Aquí hay un esquema usando un contador:
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}); } }); }); } });PD: parece que este código permite que cualquier cliente ejecute cualquier programa arbitrario en el servidor (si está en la ruta o pueden construir la ruta completa). Eso parece muy peligroso.
PPS La acumulación de tmp fuera del controlador como lo estaba haciendo en su código original es un desastre para varios usuarios que usan su servidor, ya que varias solicitudes pueden afectar el valor de tmp de cualquier otro. Los datos acumulados como este deben estar en una variable local dentro del controlador de solicitudes o en una propiedad en el objeto de la solicitud para que nunca entren en conflicto con otras solicitudes en proceso.