Angular Dependency Injection — Inject service inside custom Rxjs operators
Madhu Sudhanan P
Posted on November 24, 2024
Angular is an opiniated framework. It’s really an excitement to see how its diverging towards developer flexibility and becoming stronger day by day. I believe it’s a happy era for the Angular lovers.
Dependency injection and RxJS — In my opinion, are powerful features which made Angular unique and flexible. RxJS custom operators are a great way to compose complex logic into reusable functions.
Recently I came across a usecase where I need to create a custom RxJS operator which uses service to achieve some complex usecase.
You can use inject
method to access desired service instance, inject must be used within dependency injection context though. To achieve this, Rxjs operator can be registered as a InjectionToken
which uses useFactory
function to instantiate its value. Since useFactory
is a injection context, the services can be injected without any problem using the inject method.
Let’s see how the below service can be injected in a rxjs custom operator.
// Service
@Injectable({
providedIn: 'root',
})
export class Multiplier {
public transfrom(val: number) {
return val * 2;
}
}
The below custom RxJS operator simply multiple the given value with 2 using the Multiplier service.
import { inject, InjectionToken } from '@angular/core';
import { Multiplier } from '../services/multiplier';
import { map, OperatorFunction, pipe } from 'rxjs';
export const MULTIPLIER_OPERATOR: InjectionToken<OperatorFunction<number, number>>
= new InjectionToken('Multipler operator', {
factory(): OperatorFunction<number, number> {
const multipler = inject(Multiplier); // injected Multipler service
return pipe(map((x: number) => multipler.transfrom(x)));
},
});
Now the custom operator can be used within the components using the @Inject
decorator.
import { Component, Inject } from '@angular/core';
import { BehaviorSubject, Observable, of, OperatorFunction } from 'rxjs';
import { MULTIPLIER_OPERATOR } from './rxjs-operators/custom';
import { CommonModule } from '@angular/common';
export class App {
private _count = 1;
public base = new BehaviorSubject(this._count);
public val = new Observable();
constructor(
@Inject(MULTIPLIER_OPERATOR) // injected custom operator
private multiplier: OperatorFunction<number, number>) {
this.val = this.base.pipe(this.multiplier); // used rxjs operator
}
.....
}
There are several other ways to achieve this same usecase like creating a separate service and a method that would return custom operator. But I like InjectionToken approach due to its self containability. RxJS isn’t going anywhere in near future even with introduction of signals so it’s worth experimiting on it.
You can see the full working example here.
Happy Coding…🎉
Posted on November 24, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 24, 2024