javascript - 带有 js 的单例导致内存泄漏
问题描述
我正在开发一个 chrome 扩展,我希望配置对象被创建一次并在应用程序的所有部分之间共享。取决于配置的第二个对象也应该创建一次并共享。每个对象都包含承诺。
function config () {
this.instanse = null;
this.status = 'pending';
this.data = defualtData;
// contructor
this.init = async () => {
if(this.instanse) return this.instanse;
this.instanse = this;
await this.loadData();
}
this.loadData = async () => { // bring data from chrome store }
}
第二个对象如下:
function WebsitesClass (config) {
this.instanse = null;
this.status = 'pending';
this.data = config.data.userProfile;
// contructor
this.init = async () => {
if(this.instanse) return this.instanse;
this.instanse = this;
await this.loadAnotherData(this.data);
}
this.loadAnotherData = async () => { // bring data from chrome store; }
}
然后我在一个文件中实例化这两个对象:
// init.js
const configObj = new Config();
export const hudConfigInit = () => {
if (configObj.instance) return configObj;
configObj.init();
return configObj;
}
export const hudConfig = hudConfigInit();
const websitesObj = new WebsitesClass(hudConfig);
const hudWebsitesObjInit = () => {
websitesObj.init();
return websitesObj;
}
export const hudWebsites = hudWebsitesObjInit();
然后我会将创建的对象导入到我的所有文件中,例如:
import {hudConfig, hudWbsites} from 'init.js';
window.inload = async() => {
await waitFor([ hudConfig, hudWebsites ]);
// start work here ...
}
问题是我在这个实现的某个地方面临一个奇怪的无限循环。
我做错什么了?对此有什么建议吗?
编辑
我使用这个函数来确保每个函数都正确加载:
/**
* @summary detect when a single object finishes loading.
* @param {object} obj the object that we are waiting for
* @returns {boolean} true when the object finishes loading
*/
const finishWorking = async (obj) => {
if (helpers.isFunction(obj.refresh)) {
switch (obj.type) {
case HUD_OBJECT_TYPES.hudConfig: { await hudConfig.refresh(); break; }
case HUD_OBJECT_TYPES.hudWebsites: { await hudWebsites.refresh(hudConfig); break; }
// case HUD_OBJECT_TYPES.hudSubscriptions: { await hudSubscriptions.refresh(hudConfig); break; }
}
}
return new Promise(async (resolve, reject) => {
while (obj.status !== workStatus.done) {
await helpers.sleep(1000);
// finishWorking(obj)
/** ->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.infinite loop was here **/
}
resolve(true);
})
}
解决方案
因为它是 chrome 扩展:
- 在弹出窗口和选项页面之间共享对象引用将为它们中的每一个创建一个副本,因为它们中的每一个都是一个单独的文档。
- 试图在后台和其他组件之间共享对象引用会导致错误,导致这种共享是不允许的。
解决方案是:
- 在最顶部的背景页面上实例化对象。
- 使用函数与该对象交互
chrome.runtime.sendMessage()
,发送正确的消息并将响应定向到正确的对象方法。
所以:
// background.js
const configObj = new Config();
chrome.runtime.onMessage(async (req, sender, sendResponse)=>{
switch(req.type){
case "refreshConfig" : {
await hudConfig.refresh();
sendResponse(hudConfig.data);
}
}
})
您也可以从弹出窗口或选项或内容发送消息:
const refreshButton = document.querySelector('#save');
refreshButton.onClick(async() => {
chrome.runtime.sendMessage({type: "refreshConfig"}, (data) =>{
setData(data); //data is here the object after the update.
})
})
推荐阅读
- java - 有没有办法用 osmdroid 激活标签?
- android - 在 Android 上应用 StrictMode 时出现 setUidCleartextNetworkPolicy 上的 IllegalStateException
- node.js - 以管理员身份启动节点 js 子进程
- hive - 在外部 Hive 表 (Hive 2.3.6) 上执行 MSCK REPAIR TABLE 时出错
- azure - 使用图形 API 和登录名作为用户名创建用户时,Azure AD B2C 密码重置不起作用
- jasper-reports - 无法将数据从主报告传递到报告中的子报告
- android - Android将数据发送到另一个应用程序的后台服务
- c++ - 如何在 qml 中通过父组件设置 C++ 模型?
- c++ - UE4 项目链接错误,描述为空
- ios - iOS:iOS 目标中的 tvOS API 可用性错误 | 迅捷包