jlh
jlh

Reputation: 4667

Attach 'on subscribe' callback to observable

My angular 4 application has a rest service that is being injected into various components and returns observables. In one specific component I'd like to have a count of pending requests. I currently do this by incrementing a counter when a request is being made and decrementing it when the request has completed (successfully or not). Somewhat like this:

export class MyComponent {
    nRunningRequests = 0;

    constructor(private restService: RestService) {
    }

    loadData(type: string): Observable<any> {
        // this line is wrongly executed too soon, since the request
        // is not actually done yet
        this.nRunningRequests++;
        return this.restService.fetchData(type)
            .finally(() => this.nRunningOperations--);
    }

    loadNames(): Observable<any> {
        this.loadData('names');
        // oops, didn't subscribe, so no request is actually being done
        // but nRunningRequests is now wrong
    }
}

The problem I have is that if I don't actually subscribe() to the observable, no request is being triggered and therefore the counter shouldn't have been incremented. Is there a way to attach a callback to be called at subscription time? Something along the lines of:

    loadData(type: string): Observable<any> {
        return this.restService.fetchData(type)
            .initially(() => this.nRunningRequests++)
            .finally(() => this.nRunningRequests--);
    }

I could also move the counting logic into the rest service, but that doesn't make sense, because I only want to count the requests from this one component.

Upvotes: 3

Views: 407

Answers (1)

martin
martin

Reputation: 96891

In some Rx variants there is what you need (maybe also in RxJS 4, I'm not sure now) but it's not available as an operator in RxJS 5.

The easiest way to do what you want is to use Observable.defer to create the source Observable:

Observable.defer(() => {
    this.nRunningRequests++
    return this.restService.fetchData(type)
  })
  .finally(() => this.nRunningRequests--);

Upvotes: 2

Related Questions