Я новичок в node.js и Electron и пытаюсь запустить внешнюю команду в Electron и показать результат с помощью HTML.
Я сделал версию HTTP-сервер-клиент с node.js, который отлично работает Но не удалось заставить его работать с Электроном, даже после следующих многочисленных ответов, таких как
Ни один из них не работал для меня в Electron.
Node.js версия работает.
Я показываю свой рабочий node.js код следующим образом. Этот код после запуска node index.js
и открытия localhost:8888/start
в браузере покажет вывод ls -al
на веб-странице:
// index.js
var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");
var handle = {};
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;
server.start(router.route, handle);
Сервер HTTP:
// server.js
var http = require("http");
var url = require("url");
function start(route, handle) {
http.createServer(function(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
route(handle, pathname, response);
}).listen(8888);
console.log("Server has started.");
}
exports.start = start;
Маршрутизатор, который обрабатывает два запроса, т.е. start/upload
, по-разному:
//router.js
function route(handle, pathname, response) {
console.log("About to route a request for " + pathname);
if (typeof handle[pathname] == 'function') {
handle[pathname](response);
} else {
console.log("No request handler found for " + pathname);
// send an HTTP status and content-type in the HTTP response *header*
// back to the browser that requested your server).
response.writeHead(404, {"Content-Type": "text/plain"});
// send text in the HTTP response *body*.
response.write("404 Not found");
// finish the response.
response.end();
}
}
exports.route=route;
Фактические обработчики запросов:
// requestHandlers.js
var exec = require("child_process").exec;
function start(response) {
console.log("Request handler 'start' was called.");
var content = "empty";
exec("ls -al",
{timeout: 10000, maxBuffer: 20000*1024},
function(error, stdout, stderr) {
// send an HTTP status 200 and content-type in the HTTP response *header*
// back to the browser that requested your server).
response.writeHead(200, {"Content-Type": "text/plain"});
// send text in the HTTP response *body*.
response.write(stdout);
// finish the response.
response.end();
});
}
function upload(response) {
console.log("Request handler 'upload' was called.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("You've uploaded data");
response.end();
}
exports.start = start;
exports.upload = upload;
Приведенный выше код работал для меня в Safari.
Сбой версии Electron
Теперь я хотел сделать то же самое с Electron: введите команду в поле ввода, запустите ее через кнопку отправки и отобразите результат на той же странице ниже элементы управления. Вот мой основной процесс:
// main.js
const {app, BrowserWindow} = require('electron');
let mainWindow = null;
app.on('ready', () => {
console.log('Hello from Electron');
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true
}
});
mainWindow.webContents.openDevTools()
mainWindow.webContents.loadFile('./app/index.html');
// mainWindow events, within app lifecycle
mainWindow.webContents.on('did-fail-load', function() {
console.log("Failed to load index.html");
})
})
Теперь процесс рендеринга:
// renderer.js
const { shell } = require('electron');
const parser = new DOMParser();
const resultSection = document.querySelector('.results');
const errorMessage = document.querySelector('.error-message');
const newCmdForm = document.querySelector('.new-cmd-form');
const newCmd = document.querySelector('.new-external-cmd');
const newCmdSubmit = document.querySelector('.new-cmd-run');
const clearStorageButton = document.querySelector('.clear-results');
newLinkForm.addEventListener('submit', (event) => {
const cmd = newCmd.value;
processCmd(cmd);
});
const processCmd = (cmd) => {
var exec = require('child_process').exec;
exec("ls -al", {timeout: 10000, maxBuffer: 20000*1024},
function(error, stdout, stderr) {
var out = stdout.toString();
var result =
'<div class="text"' +
`<h3>${out}</h3>` +
'</div>';
resultSection.innerHTML = result;
console.log(result)
});
}
const renderResults = () => {
resultSection.innerHTML = '';
};
renderResults();
Вот страница:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self' 'unsafe-inline';
connect-src *">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Cmdlet</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<h1>Cmdlet</h1>
<div class="error-message"></div>
<section class="input-new-cmd">
<form class="new-cmd-form">
<input type="text" class="new-external-cmd" placeholder="default command" size="100" required>
<input type="submit" class="new-cmd-run" value="Run">
</form>
</section>
<section class="results"></section>
<section class="controls">
<button class="clear-results">Clear</button>
</section>
<script>
require('./renderer');
</script>
</html>
Зная, что вызов внешней команды isyn c, я поместил код обновления рендерера в обратный вызов. Однако этот код показывает [object Object]
в целевой области вместо вывода ls -al
.
Где я был не прав?