Мы создаем приложение Electron, которое позволяет пользователям предоставлять собственные «модули» для запуска. Мы ищем способ требовать модули, но затем удаляем или убиваем модули, если это необходимо. Мы просмотрели несколько учебных пособий, в которых обсуждается эта топи c, но мы не можем заставить модули полностью завершиться. Мы исследовали это с помощью таймеров внутри модулей и можем наблюдать, как таймеры продолжают работать даже после удаления ссылки на модуль.
https://repl.it/repls/QuerulousSorrowfulQuery
index.js
// Load module
let Mod = require('./mod.js');
// Call the module function (which starts a setInterval)
Mod();
// Delete the module after 3 seconds
setTimeout(function () {
Mod = null;
delete Mod;
console.log('Deleted!')
}, 3000);
./mod.js
function Mod() {
setInterval(function () {
console.log('Mod log');
}, 1000);
}
module.exports = Mod;
Ожидаемый результат
Mod log
Mod log
Deleted!
Фактический результат
Mod log
Mod log
Deleted!
Mod log
...
(continues to log 'Mod log' indefinitely)
Может быть, мы переосмысливаем это, и, возможно, модули не будут загружать память, но загружаемые нами модули будут иметь очень интенсивные рабочие нагрузки, и возможность остановить их по своему усмотрению кажется важной. Редактировать с реальным вариантом использования
Вот как мы в настоящее время используем эту технику. Две проблемы - загрузка модуля надлежащим образом и выгрузка модуля после его завершения.
renderer.js
(выполняется в контексте браузера с доступом к document
, et c)
const webview = document.getElementById('webview'); // A webview object essentially gives us control over a webpage similar to how one can control an iframe in a regular browser.
const url = 'https://ourserver.com/module.js';
let mod;
request({
method: 'get',
url: url,
}, function (err, httpResponse, body) {
if (!err) {
mod = requireFromString(body, url); // Module is loaded
mod(webview); // Module is run
// ...
// Some time later, the module needs to be 'unloaded'.
// We are currently 'unloading' it by dereferencing the 'mod' variable, but as mentioned above, this doesn't really work. So we would like to have a way to wipe the module and timers and etc and free up any memory or resources it was using!
mod = null;
delete mod;
}
})
function requireFromString(src, filename) {
var Module = module.constructor;
var m = new Module();
m._compile(src, filename);
return m.exports;
}
https://ourserver.com/module.js
// This code module will only have access to node modules that are packaged with our app but that is OK for now!
let _ = require('lodash');
let obj = {
key: 'value'
}
async function main(webview) {
console.log(_.get(obj, 'key')) // prints 'value'
webview.loadURL('https://google.com') // loads Google in the web browser
}
module.exports = main;
На всякий случай, если любой читающий не знаком с Electron, renderer.js
имеет доступ к элементам 'webview', которые почти идентичны элементам iframe. Вот почему его передача в модуль. js позволит модулю получить доступ к манипулированию веб-страницей, такой как изменение URL-адреса, нажатие кнопок на этой веб-странице и т. Д. c.