Is it possible to have only one(!) instance of a custom pure pipe in an Angular project?
It seems to me that Angular is creating for every different component in the project a new instance of my custom pipe. It calls the constructor of my pipe for every different component I am using the pipe in.
Its about the cachability. I would love to have throughout my different components using that one pipe in their template only one instance of my custom pure pipe!
I have just come across this exact same issue where I wanted to use a pipe to provide temporary images while a http request was pending and then cache the result of this image in the pipe, so that next time an image with the same src is loaded it can pull straight from cache.
This is what I came up with.
@Pipe({
name: 'examplePipe',
pure: false,
})
export class ExamplePipe implements PipeTransform, OnDestroy {
private subscriptions: Subscription[] = [];
constructor(private cacheService: ExamplePipeCacheService<{ url: string }>) {}
ngOnDestroy(): void {
for (let s of this.subscriptions) {
s.unsubscribe();
}
}
transform(value: string, ...args: any[]) {
if (!this.cacheService.cache[value]) {
console.log(`>> ${value} NOT in cache << `);
//emit one item
const example = of(null);
//delay output of each by an extra second
const obs = merge(
example.pipe(mapTo('https://via.placeholder.com/50')),
example.pipe(mapTo('https://via.placeholder.com/150'), delay(3000)),
example.pipe(mapTo('https://via.placeholder.com/250'), delay(4000)),
example.pipe(mapTo(value), delay(5000))
);
this.subscriptions.push(
obs.subscribe((v) => {
console.log(`++ SET ${value} in cache ++ `);
this.cacheService.cache[value] = { url: v };
})
);
} else {
console.log(`GET ${value} from cache`);
}
return this.cacheService.cache[value].url;
}
}
@Injectable({
providedIn: 'root',
})
export class ExamplePipeCacheService<Value> {
public cache: { [index: string]: Value } = {};
}
It uses a singleton service to store the cache so then whenever / wherever ExamplePipe
is used, it will always pull its cache from the same instance.
In this working example https://stackblitz.com/edit/angular-ivy-5wwbc2?file=src/app/app.component.ts There are 3 images that load of which 2 are pointing to the same src url. You can see that the first time a unique image src is loaded, it is added to the cache, and then all following calls, using the src value as the cache key, attempts to drag the existing value from cache before making a new request.
Note that obs
could be a http request, or any observable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With