【发布时间】:2020-05-11 21:34:26
【问题描述】:
我们正在构建一个允许用户提供自己的“模块”来运行的 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);
./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等的浏览器上下文中运行)
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 可以访问与 iframe 几乎相同的“webview”元素。这就是为什么将它传递给“module.js”将允许模块访问操作网页,例如更改 URL、单击该网页上的按钮等。
【问题讨论】:
-
是的,我看到了这个问题并尝试了几乎所有的答案。但是,即使将答案应用于此问题中的示例,计时器仍会记录内容!您还有其他建议吗?
-
它是基于网络的应用程序吗?我的意思是这个模块会在浏览器端运行吗?顺便说一句,您不能使用
delete运算符删除函数,它只能用于删除对象属性 -
您是否尝试先将
Mod分配给某个局部变量,然后在超时清除/设置为 null 该变量?或者你可以使用clearInterval? -
@AhmetZeybek 这是在 Electron 应用程序上,应该提到我的错误。
标签: javascript node.js module electron require