T M*_*ack 4 javascript module require node.js electron
我们正在构建一个 Electron 应用程序,允许用户提供自己的“模块”来运行。我们正在寻找一种方法来需要这些模块,但如果需要的话,然后删除或终止这些模块。我们看过一些似乎讨论这个主题的教程,但我们似乎无法让模块完全终止。我们通过在模块内使用计时器来探索这一点,并且可以观察到即使在删除模块引用后计时器仍在运行。
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);
Run Code Online (Sandbox Code Playgroud)
./mod.js
function Mod() {
setInterval(function () {
console.log('Mod log');
}, 1000);
}
module.exports = Mod;
Run Code Online (Sandbox Code Playgroud)
预期产出
Mod log
Mod log
Deleted!
Run Code Online (Sandbox Code Playgroud)
实际产量
Mod log
Mod log
Deleted!
Mod log
...
(continues to log 'Mod log' indefinitely)
Run Code Online (Sandbox Code Playgroud)
也许我们想得太多了,也许这些模块不会占用内存,但我们加载的模块将具有非常密集的工作负载,并且能够随意停止它们似乎很重要。
根据实际用例进行编辑
这就是我们目前使用该技术的方式。两个问题是以正确的方式加载模块以及完成后卸载模块。
renderer.js(在浏览器上下文中运行,可以访问document等)
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;
}
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
以防万一读者不熟悉 Electron,可以renderer.js访问与 iframe 几乎相同的“webview”元素。这就是为什么将其传递给“module.js”将允许模块访问操纵网页,例如更改 URL、单击该网页上的按钮等。
无法终止模块并停止或关闭它正在使用的任何资源。这不是 Node.js 的功能。这样的模块可以有计时器、打开的文件、打开的套接字、运行的服务器等......此外,node.js 不提供“卸载”曾经加载的代码的方法。
您可以从模块缓存中删除模块,但这不会影响现有的、已加载的代码或其资源。
我所知道的唯一万无一失的方法是将用户的模块加载到作为子进程加载的单独的node.js应用程序中,然后您可以退出该进程或终止该进程,然后操作系统将回收它正在使用的任何资源并卸载一切都来自记忆。这种子进程方案还有一个优点,即用户的代码与主服务器代码更加隔离。如果您愿意,您甚至可以通过在虚拟机中运行其他进程来进一步隔离它。
| 归档时间: |
|
| 查看次数: |
1797 次 |
| 最近记录: |