Purge the inversify-js container and fetch fresh service instances

My frontend application in react-native utilizes inversify-js for service classes.

I have implemented an IOC structure where services are shared as singleton instances, each with an init/destroy method to manage internal state.

While the init/destroy mechanism works well, I am seeking a way to "clear" the inversify container singletons to rebuild all services from scratch when needed.

For example:

src/services/A.ts

@injectable()
export class A extends Service {
  constructor() {
    super();
  }

  init() {
    super.init();

    // [...] Initialize A's state
  }

  destroy() {
    // [...] Destroy A's state

    super.destroy();
  }

  method() {
    // [...] Provide functionality to other services (maintaining A's state)
  }
}

src/inversify/container.ts

export const containerModule = new ContainerModule((bind) => {
  // Services
  bind<A>(A).toSelf().inSingletonScope();
});

const container = new Container();

container.load(containerModule);

export default container;

index.ts

let a = container.get<A>(A);

// [...] use service

// Resetting the container and creating new singleton instances
container.unbind(A);
container.bind<A>(A).toSelf().inSingletonScope();
a = container.get<A>(A);

For more information on resetting scoped containers in InversifyJS, you can refer to this stackoverflow thread: Reset scoped container in inversifyjs

Answer №1

To ensure proper cleanup before unbinding a service, utilize the @preDestroy decorator on a class method. See more details at Inversify-docs#preDestroy

The method decorated with @preDestroy will be executed just before a service is unbound to release any cached instances. It is important to note that only methods belonging to bindings in singleton scope can have this decorator.

@preDestroy
destroy() {
  console.log('Service about to be unbound. Destroying now.');
}

Answer №2

In my proposed solution, I recommend discarding the current container and starting fresh with a new instance for a clean and easy-to-understand approach.

However, upon further examination of the source code, I discovered that this functionality is already built-in.

container.unbindAll() does the trick!

This API effectively resets the container to a pristine state (almost pristine, I'll explain later) without requiring the creation of a new instance. Check out the source code here.

As mentioned earlier, the term "almost pristine" comes from the fact that the container also features a lesser-known (at least to me) capability known as snapshots. It turns out that you can store multiple snapshots of binding setups within a single container.

Quite intriguing 🤔. By taking a snapshot of an empty container before adding any bindings, and then restoring it later, you essentially perform a "reset".

Finally, using

container.unload(containerModule)
is completely valid and not at all hacky. Some may even refer to it as a selective reset 😂

If you delve into the source code, you'll see that behind the scenes of these methods lies the manipulation of the internal _bindingDictionary, which serves as the storage for all bindings.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What advantages does using an RxJS Subject have over handling multiple event listeners individually in terms of speed

After investigating a page's slow performance, I identified an angular directive as the root cause. The culprit was a piece of code that registered event listeners on the window keydown event multiple times: @HostListener('window:keydown', ...

Guide to incorporating the useEffect hook within a React Native View

I am trying to use useEffect within a return statement (inside a Text element nested inside multiple View elements), and my understanding is that I need to use "{...}" syntax to indicate that the code written is actual JavaScript. However, when I implement ...

Invoke the function once the database information has been retrieved

I am new to Node.js and I am attempting to execute a function after running a select query using the code below: private displayUserInfo(): any { let connect = this.connect(); connect.connect(function(err: any) { if (err) throw err; ...

Angular developers may encounter a dependency conflict while attempting to install ngx-cookie

I'm currently facing an issue while attempting to add the ngx-cookie package for utilizing the CookieService in my application. Unfortunately, I am encountering some dependency conflicts that look like the following: $ npm install ngx-cookie --save np ...

I require adding a new line of information into the database table

I am looking for help with adding data into a table without any user inputs. Specifically, I want to add data by passing them into an array and then be able to call them at the "Add Site" button so that the row is added into the table. Can someone assist m ...

Collective picture in the exhibit

I recently created a photo gallery that showcases various images sorted by categories. In this setup, I have one object containing both images and their respective categories, and another object solely dedicated to storing the categories. The challenge I ...

When working in React, I often encounter the frustrating TypeError: Cannot read property 'content' of undefined error

Trying to customize a React project, I attempted to add a class to a div using the following code: <div className={styles.content}> In the case of deleting the Data Source, you will lose all configuration sett ...

Generating output from a callback function in TypeScript

When I execute a graphql query, the showUsers function is supposed to display all users (styled as boxes). However, at the moment, nothing is showing up. I am utilizing a functional component instead of a class component. This function is invoked after m ...

Manipulating CSS Class Properties Using JavaScript

In my JavaScript application, there is a functionality that loads a list of items for users to click and view detailed information in a separate div on the page. Users should be able to interact with and make modifications to these individual item overview ...

Steps for modifying the look of a button to display an arrow upon being clicked with CSS

Looking to enhance the visual appearance of a button by having an arrow emerge from it upon clicking, all done through CSS. Currently developing a React application utilizing TypeScript. Upon clicking the next button, the arrow should transition from the ...

The validation process in Redux forms

Imagine we have the following types defined: interface MyFormFields { FirstName: string; LastName: string; } type FieldsType = keyof MyFormFields; const field1: FieldsType = "c"; const field2 = "c" as FieldsType; Now, I am looking to implemen ...

Can you clarify the significance of the "1" in this particular Typescript code snippet?

Can anyone provide some insight into the purpose of this '1' in the following TS code snippet? decryptPassPhrase() { this.$encrypt.setPrivateKey(privateKey); this.decryptedPassPhrase = this.$encrypt.decrypt(this.encryptedPassPhrase); ...

How to prevent unnecessary new instances from being created by the Inject() function in Angular

Can someone please clarify if the inject() function provides different instances of a service? I suspect this might be why my code is not functioning as expected. Let's examine the code snippet below: { path: 'recipes', comp ...

Is there a way to adjust the width of a table cell in Material UI using React?

I encountered a problem where I am attempting to adjust the width of a table cell, specifically in Typescript. However, I am only able to choose between medium and small sizes for TableCellProps. Is there a workaround for this issue? I am looking to expand ...

What sets a module apart from a script?

As I delve into the depths of TypeScript documentation to grasp the concept of modules, particularly ES6 modules, I stumbled upon some interesting insights. typescript-modules - this documentation talks about typescript modules and highlights an important ...

Leverage es6 classes along with mongoose in typescript to utilize loadClass functionality

I've been struggling with a problem and despite my exhaustive search on Google, I still haven't found a solution. My issue revolves around incorporating es6 classes with mongoose using the schema.loadClass(class) method. Unfortunately, when worki ...

Interface of TypeScript Undetermined

Currently, I am developing a Demo API Wrapper specifically for Roblox. During the development process, I have come across a certain issue that I would like to address. My aim is to send a request and then return all the data in the manner of an API wrapper ...

Using Typescript to transform a list into function arguments

My current challenge involves a set of arguments structured like so: const args: FeatureEventArg[] = [ { name: 'username', type: 'string', }, { name: 'message', type: 'string', }, { name ...

The Swipe animation encountered a problem because it attempted to access an undefined object called singleValue.StopTracking

I am encountering a TypeError while trying to use the Delete on Swipe function: undefined is not an object(evaluating 'singleValue.StopTracking') The project is being run using expo When I swipe, an error is returned by expo. Clicking dismiss r ...

The external typing file encounters an issue when trying to locate the relative path to its own index.d.ts file

While working on my project and using react-color as a dependency, I encountered an issue with the tsc import failing. The error message displayed: node_modules/@types/react-color/lib/components/sketch/Sketch.d.ts(2,41): error TS2307: Cannot find module & ...