“This is the third day of my participation in the First Challenge 2022. For details: First Challenge 2022”

preface

Dependency injection (DI) : dependency injection (DI) : dependency injection (DI) : dependency injection (DI) : dependency injection (DI) : dependency injection (DI) How should he behave with JS?

What is dependency injection

Dependency injection (DI) is a design principle used in object-oriented programming to reduce coupling between code.

Let’s start with a piece of code

class Video{
    constructor(url){}}class Note{
    video: Video
    constructor(){
        this.video = new Video("https://aaaaa.mp4")}getScreenshot(){
        this.video.getScreenshot()
    }
}

const note = new Note()
note.getScreenshot()
Copy the code

Let’s say we use a video class and it has a getScreenshot method in it, and when instantiating the video class, we need to pass in a video URL. Now we have a note class that needs to call the screenshot method under the video class, so we can say that the note class is dependent on the video class. So inside the note class, we need to instantiate the video class, so that we can get the instance object of the video class in the note class, and call the screenshot method inside it.

The coupling degree of the above code is too high, so it is not recommended to use it. For example, if the Video address of the Video is changed, then the incoming Video URL needs to be changed in the Note. This assumes that if there are more classes dependent on the Video class, then all parts will have to be changed once the change is made, which is very inconvenient.

Next use dependency injection to solve the above problem:

class Note{
    video: Video
    constructor(video: Video){
        this.video = Video; }}const video = new Video("https://aaaaa.mp4")
const note = new Note(video)
Copy the code

We instantiate the video class outside the class, and pass the instance to the note class through the way of parameter passing, by this way can successfully solve the problem of coupling degree is too high, we call the way of parameter passing instance: injection.

advantages

Dependency injection reduces coupling between codes and increases code maintainability. Code changes in the video class will no longer affect the notes class.

Angular’s DI framework

One area that is not ideal is that we need to instantiate the video class outside of the class. Although this is the only area, we still hope that no changes to the video class inside will affect the external code.

The Angular DI framework eliminates the need to instantiate the video class. It hides the dependency injection process and allows developers to use complex dependency injection functionality with very simple code.

DI in Angular has four core concepts:

  1. Dependency: An instance object, a service instance object, on which the component depends
  2. Token: Obtains the identity of a service instance object. Angular maintains a number of instance objects, and when we need to obtain them, we use the identity to obtain them
  3. Injector: The Injector is responsible for creating and maintaining service instance objects, injecting service instance objects into components, and passing them to components as parameters
  4. Procider: object used to configure the injector, specify the service class to create the service instance object and obtain the identity of the instance object

Injector Injector

We start by creating an injector using the basic syntax provided by Angular

  1. Creating an injector
import { ReflectiveInjector } from "@angular/core"
/ / service class
class Video{}
// Create an injector and pass in the service class
const injector = ReflectiveInjector.resolveAndCreate([ Video ])
Copy the code

ReflectiveInjector the resolveAndCreate method is used to create an injector. It takes an array of the classes where you want to create an instance object. The resolveAndCreate method returns an injector. Gets the service class instance object in the injector

const video = injector.get(Video)
Copy the code

The Injector has a get method that has been used to pass in an id and get an instance object. The default id is the name of the service class (Video)

Angular gives us the DI framework so that we don’t need to manually instantiate a class to get an instance of it, it does it for us.

  1. The instance object of the service is a singleton that the injector regrets caching when creating the service instance
const video1 = injector.get(Video)
const video2 = injector.get(Video)

console.log(video1 === video1)//true
Copy the code

That is, no matter how many times the framework fetches an instance object, it returns the same instance object

  1. But we can create multiple injectors that do not return the same service instantiation object
const injector1 = ReflectiveInjector.resolveAndCreate([ Video ]) const injector2 = ReflectiveInjector.resolveAndCreate([  Video ]) const video1 = injector1.get(Video) const video2 = injector2.get(Video) console.log(video1 === video1)//falseCopy the code
  1. ResolveAndCreateChild creates a child injector. The relationship between the parent injector and the child injector is similar to the js scope chain. If the current injector cannot find the child injector, the parent injector will search for it.
const injector = ReflectiveInjector.resolveAndCreate([ Video ])
const injectorChild = injector.resolveAndCreateChild([])

const video1 = injector.get(Video)
const video2 = injectorChild.get(Video)

console.log(video1 === video1)//true
Copy the code

As shown in the above code, when creating a child injector, no arguments are passed. However, when instantiating the child injector, since there is no Video service, it will look for the parent. Of course, the parent Video service is found and instantiated, so the latter two instantiated objects are equal

conclusion

This article introduces dependency injection solutions and how it works in its native form. It introduces the DI framework Angular provides, implements instantiation using a simple API it provides, and shows that injectors, which are also hierarchical, provide a better way to design a project. We’ll have a chance to talk about providers and more extensions later.