簡體   English   中英

singleton 與 js 導致 memory 泄漏

[英]singleton with js is causing memory leak

我正在開發一個 chrome 擴展,我希望配置 object 被創建一次並在應用程序的所有部分之間共享。 取決於配置的第二個 object 也應該創建一次並共享。 每個 object 都包含承諾。

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 } 
}

第二個 object 如下:


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 ...

}

問題是我在這個實現的某個地方面臨一個奇怪的無限循環。

我做錯了什么? 對此有什么建議嗎?

編輯

我使用這個 function 來確保每個 function 都正確加載:

/**
 * @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 擴展:

  1. 在彈出窗口和選項頁面之間共享 object 引用將為它們中的每一個創建一個副本,因為它們中的每一個都是一個單獨的文檔。
  2. 試圖在后台和其他組件之間共享 object 引用會導致錯誤,導致這種共享是不允許的。

解決方案是:

  1. 在最頂部的背景頁面上實例化 object。
  2. 使用chrome.runtime.sendMessage() function 與 object 交互,發送正確的消息並將響應定向到正確的 object 方法。

所以:

// 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.
   })
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM