Performance of using same observable in multiple places in template with async pipe

Every use of observable$ | async will create a new subscription(and therefor an individual stream) to the given observable$ – if this observable contains parts with heavy calculations or rest-calls, those calculations and rest-calls are executed individually for each async – so yes – this can have performance implications.

However this is easily fixed by extending your observable$ with .share(), to have a shared stream among all subscribers and execute all those things just once for all subscribers.
Don’t forget to add the share-operator with import "rxjs/add/operator/share";

The reason why async-pipes don’t share subscriptions by default is simply flexibility and ease of use: A simple .share() is much faster to write than creating a completely new stream, which would be required if they were to be shared by default.

Here is a quick example

@Component({
    selector: "some-comp",
    template: `
        Sub1: {{squareData$ | async}}<br>
        Sub2: {{squareData$ | async}}<br>
        Sub3: {{squareData$ | async}}
    `
})
export class SomeComponent {
    squareData$: Observable<string> = Observable.range(0, 10)
        .map(x => x * x)
        .do(x => console.log(`CalculationResult: ${x}`)
        .toArray()
        .map(squares => squares.join(", "))
        .share();  // remove this line and the console will log every result 3 times instead of 1
}

Leave a Comment