¿Hay alguna forma de detectar el inicio de la suscripción de un rxjs observable dentro de la tubería?
Quiero activar un indicador de carga cuando se suscriba un http observable (destruido cuando se haya finalizado la respuesta).
¿O tengo que crear un contenedor observable para esta acción?
Depende de la versión de RxJS que esté utilizando. Con RxJS <7.3 puedes usar defer() :
defer(() => { loadingFlag = true; return this.http.doyourrequest().pipe( finalize(() => loadingFlag = false), ); }); Desde RxJS >= 7.3, puede usar nuevos controladores de eventos para tap() :
this.http.doyourrequest().pipe( tap({ subscribe: () => loadingFlag = true, finalize: () => loadingFlag = false, }), );dado que cada suscripción a http observable provoca una nueva llamada http, es seguro establecer dicha bandera fuera de la canalización, al menos así es como lo hago.
getSomeData(){ loadingFlag=true; return this.http.doyourrequest().pipe(finalize(()=>loadingFlag=false)); }si realmente desea pasar por el subconteo (que siempre llega a 0 después de cada solicitud debido a la finalización de http obs), verifique la implementación de los operadores refCount() y share() que cuentan internamente a los suscriptores
Editar:
Puede encapsular la configuración de la bandera utilizando un observable ficticio como punto de entrada, por ejemplo
getSomeData(){ return of(null).pipe( tap(()=>loadingFlag=true), switchMapTo(this.http.doyourrequest()), finalize(()=>loadingFlag=false) ) }En lugar de establecer algún indicador como efecto secundario en su transmisión, intente crear un observable que devuelva el estado de su solicitud.
readonly makeRequestSubject = new Subject<RequestParams>(); readonly request$ = makeRequestSubject.pipe( switchMap(params => this.doRequest(params).pipe( map(result => ({ params, result, state: 'complete' })), catchError(error => ({ error, params, state: 'error' })) startWith({ params, state: 'loading' }) ), startWith({ state: 'notstarted' }), shareReplay(1) ); readonly isLoading$ = this.request.pipe(map(x => x === 'loading'), distinctUntilChanged()); readonly results$ = this.request.pipe(map(x => x === 'complete' ? x.results : []));