简体   繁体   中英

singleton with js is causing memory leak

I'm developing a chrome extension, I want the config object, to be created once and shared between all parts of the application. A second object depending on the config should be also created once and shared. Each object contains promises.

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

and the second object as follow:


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

then I instantiate the two objects at one file:


// 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();

then I will import the created objects into all of my files, like:


import {hudConfig, hudWbsites} from 'init.js';

window.inload = async() => {

 await waitFor([ hudConfig, hudWebsites ]);

   // start work here ...

}

the problem is I'm facing a strange infinite loop somewhere in this implementation.

what did I do wrong? any suggestions on this?

Edit

I use this function to make sure that every function is loaded correctly:

/**
 * @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);
    })
}

since it is a chrome extension:

  1. sharing the object reference between the popup and the options page will create a copy for each of them since each of them is a separate document.
  2. trying to share object reference between the background and other components will cause an error, cause this kind of sharing is not allowed.

the solution was:

  1. instantiate the object on the very top background page.
  2. interact with that object using chrome.runtime.sendMessage() function, sending the right message and directing the response to the right object method.

so:

// background.js

const configObj = new Config();

chrome.runtime.onMessage(async (req, sender, sendResponse)=>{
   switch(req.type){

    case "refreshConfig" : {
          await hudConfig.refresh();
          sendResponse(hudConfig.data);
         }
    }

})

also you can send a message from popup or options or content as:


 const refreshButton = document.querySelector('#save');

refreshButton.onClick(async() => {

  chrome.runtime.sendMessage({type: "refreshConfig"}, (data) =>{

      setData(data); //data is here the object after the update.
   })
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM