Require independent instances of module inside class

31 Views Asked by At

I am a beginner in nodejs. I am developing a vscode extension based on this guide. I defined a class that requires an external js module, e.g. :

thepanel.ts:

import * as vscode from "vscode";
var externalLibrary = require("@x/y");  

export class myPanel {
   public static currentPanel: myPanel| undefined;
   private constructor( panel: vscode.webviewPanel, extensionUri: vscode.Uri, someIdentifier:string){
          //.. initialization of MyPanel.. 
          externalLibrary.someInitializationMethod(someIdentifier);  
         //^ This makes an important setup within externalLibrary based on `someIdentifier`. 
   }

    public static render (extensionUri: vscode.Uri, someIdentifier: string, .. other parameters ..){
        const panel = vscode.window.createWebviewPanel("open-panel", "Panel", .. other parameters .. ){
           // .. stuff..
           myPanel.currentPanel = new myPanel(panel, extensionUri, someIdentifier); 
       }
    }

   //.. other stuff .. , 
   // including a method to update the information when I press a refresh button in the webview..

}

In extension.ts, I registered a command to open a new panel:

import * as vscode from 'vscode';
import { myPanel } from "./panels/thepanel.ts";

export function activate(context: vscode.ExtensionContext){
 const newPanelCommand = vscode.commands.registerCommand("myextension.newPanel", () => {
 
 // ... Some code to prompt user for `someIdentifier` or set a default value .. 

 myPanel.render(context.extensionUri, someIdentifier, .. other parameters .. );
}
}

Upon testing the extension, I:

  1. Open a new panel with someIdentifier1. It works and shows the information I expect to see given someIdentifier1. I press a button that updates the information displayed on the webview, and I get the expected updated information, I can do this as many times as I want and get the expected result.
  2. Open a new panel with someIdentifier2. It works and shows the information I expect to see given someIdentifier2. I press a button that updates the information displayed on the webview, and I get the expected updated information, I can do this as many times as I want and get the expected result.
  3. I go back to the first panel and press the button that updates the information displayed on the webview, but instead of getting the updated information I expect given someIdentifier1, I instead get the updated information associated to someIdentifier2.

Why?

I added the following line

console.log(externalLibrary.ready_); 

to the constructor function in myPanel just before calling externalLibrary.someInitializationMethod(someIdentifier). The .ready_ parameter should be "not_ready" prior to calling someInitializationMethod. I re-did steps 1-3, and I noticed that in step 2, .ready_ parameter was "ready", instead of "not_ready". This means that externalLibrary in the second panel is not independent from externalLibrary in the first panel.

How can I achieve having externalLibrary being completely independent for each panel?

I found this question and in it I found the explanation from the official docs that mentions that modules are cached after the first time they are loaded. In this other question I found that one solution is to delete the cache by doing:

delete require.cache[require.resolve("library")];

What I am not sure is where should I add this?

Attempted solution

I already tried to modify thepanel.ts as follows:

import * as vscode from "vscode";  

export class myPanel {
   public static currentPanel: myPanel| undefined;
   private _externalLibrary: any;

   private constructor( panel: vscode.webviewPanel, extensionUri: vscode.Uri, someIdentifier:string){
          //.. initialization of MyPanel.. 

          delete require.cache[require.resolve("@x/y")];
          this._externalLibrary = require("@x/y");


          externalLibrary.someInitializationMethod(someIdentifier);  
         //^ This makes an important setup within externalLibrary based on `someIdentifier`. 
   }

    public static render (extensionUri: vscode.Uri, someIdentifier: string, .. other parameters ..){
        const panel = vscode.window.createWebviewPanel("open-panel", "Panel", .. other parameters .. ){
           // .. stuff..
           myPanel.currentPanel = new myPanel(panel, extensionUri, someIdentifier); 
       }
    }

   //.. other stuff .. , 
   // including a method to update the information when I press a refresh button in the webview..  And importantly, in this update I make use of `externalLibrary` by using this._externalLibrary.nameOfTheMethod.. 

}

.. but I still got the same unexpected behavior.

What is the correct way to achieving independence for each instance of externalLibrary?

Again, I am a beginner with nodejs and would like to learn the best practices, so please be detailed in the explanation.

0

There are 0 best solutions below