Как контролировать (запускать, прерывать) внешнюю программу через HTML-страницу, используя ExpressJS?

Как управлять (запускать, прерывать) внешней программой через HTML-страницу с помощью ExpressJS?

Я пытаюсь создать веб-мастер настройки, который запрашивает у пользователя некоторые значения, выводит их в файл конфигурации, а затем позволяет пользователю запустить серверную программу с использованием этой конфигурации.

Я выбрал ExpressJS, так как он казался относительно легким и легким в освоении. Однако у меня нет опыта работы с веб-программированием или JavaScript вообще.

Каким-то образом мне удалось построить страницы мастера, хотя мне кажется, что я использую что-то ужасно неправильное (приложение в основном не имеет состояния и перетаскивает пользовательские значения через разные HTML-страницы, переводя предыдущие значения в скрытые поля в форме новой страницы). .).

После всех страниц мастера появляется страница «управления», где пользователь может видеть (и редактировать) вычисленную конфигурацию. На странице есть две кнопки:

Один запускает программу для проверки конфигурации и проверки на наличие ошибок. Это делается с помощью child_process.execSync(...) (так как это не занимает много времени) и работает довольно хорошо.

Другой должен запустить долгосрочную задачу в фоновом режиме. Во время выполнения задачи кнопки на странице должны быть отключены, за исключением кнопки «Прервать», которая должна убить фоновую задачу (еще не реализованную). После завершения задачи страницу необходимо перезагрузить с помощью включенных кнопок и поля состояния, в котором указано, была ли задача выполнена успешно. К сожалению, я не могу заставить это работать.

Я использую ExpressJS с мопсом.

control.js:

 var express = require('express'); var router = express.Router(); var utils = require('./utils'); var createError = require('http-errors'); var child_process = require('child_process'); router.all('/', function(req, res,next) { var status = null; if ([req.app.locals.buttons.doStuff].includes(req.body.submit)) { next(); } switch(req.body.submit) { case req.app.locals.buttons.validate: try { utils.validate(req.body.config_text); // helper function that basically calls an external program via child_process.execSync status = "config.yaml is valid!" } catch (err) { status = "config.yaml is invalid: "   err } break; case req.app.locals.buttons.doStuff: res.render('control', { title: req.app.locals.title, buttons: req.app.locals.buttons, config_data: req.body.config_text, status: status, disabled: true }); return; } res.render('control', { title: req.app.locals.title, buttons: req.app.locals.buttons, config_data: req.body.config_text, status: status }); }); router.post('/', function(req, res, next) { var status = null; console.log("Entering command mode: "   req.body.submit); switch(req.body.submit) { case req.app.locals.buttons.doStuff: status = "Doing stuff ... this will take a while (timeout after 1h)." console.log(status); child_process.exec("doStuff arg1 arg2 arg3", {cwd: req.app.locals.dostuff_directory, timeout: 3600000}, function(err, stdout, stderr) { status = "doStuff successfully finished!" if (err) { status = "Error while doing stuff: n"   stderr; } res.render('control', { title: req.app.locals.title, buttons: req.app.locals.buttons, config_data: req.body.config_text, status: status }); }); break; default: status = "Unknown command: "   req.body.submit; res.render('control', { title: req.app.locals.title, buttons: req.app.locals.buttons, config_data: req.body.config_text, status: status }); break; } }); module.exports = router; 

и соответствующий control.pug:

 extends layout // basically just places the content block into {amp}lt;body{amp}gt; block content h1= title h3 Control Page form(method="post", autocomplete="off") label(for="config_text") config.yaml textarea(name="config_text", cols="70", rows="35") = config_data pre code(name="status") = status div(class="controls") input(type="submit", name="submit", value=buttons.validate, disabled=disabled) input(type="submit", name="submit", value=buttons.doStuff, disabled=disabled) if (disabled) input(type="submit", name="submit", value=buttons.abort) 

Если я нажимаю кнопку «doStuff», кнопки отключаются, но задача не запускается, и я получаю сообщение error: Cannot set headers after they are sent to the client .

Я думаю, что вместо этого я мог бы использовать child_process.execSync в качестве обходного пути, так как это, похоже, работает, но я предполагаю, что это остановит страницу во время выполнения задачи. У меня также есть ощущение, что я должен использовать другой метод для реагирования на нажатия кнопок, чем теги HTML- form .

Как я могу добиться желаемого поведения?

Понравилась статья? Поделиться с друзьями:
JavaScript & TypeScript
Adblock
detector