Tengo el siguiente ejemplo mínimo que demuestra el problema que estoy enfrentando, donde episode
recibe un valor de la interfaz de usuario y getEpisodeTitleFromApi
es un observable de larga duración que emite una cadena.
En la situación donde episode
es nulo o mayor que 6, result$
emite una cadena vacía inmediatamente para manejar la entrada inválida o vacía.
La intención de loading$
debe ser bastante clara.
episode = new Subject<number>();
result$ = this.episode.pipe(
switchMap(episode => !episode || episode > 6 ? of('') : getEpisodeTitleFromApi(episode)),
share()
);
loading$ = merge(
this.result$.pipe(mapTo(false)),
this.episode.pipe(mapTo(true))
);
El problema es que cuando episode
es nulo o mayor que 6 y emite de inmediato, loading$
emite falso y luego verdadero.
¿Cómo puedo conectar el loading$
observable para emitir en el orden correcto o lograr el resultado deseado?
2 respuestas
Si desea que su resultado no se ejecute sincrónico, puede usar observeOn y establecer la ejecución de la tarea de macro a través de observeOn (asyncScheduler) - [RxJS - Scheduler] [1]
const episode = new Subject<number>();
const result$ = episode.pipe(
switchMap(episode => of('')),
observeOn(asyncScheduler)
);
const loading$ = merge(
result$.pipe(mapTo(false)),
episode.pipe(mapTo(true))
);
loading$.subscribe(console.error);
episode.next(1);
Output: true, false
Prueba algo como esto:
loading$ = combineLatest(
this.results$,
this.episode,
).pipe(
map(([result, episode]) => !result || episode) // show loading if result is falsy or episode
);
Es posible que deba usar el operador startWith
para iniciar cada observable, tal vez con valores predeterminados. El problema es que episode
es un tema y siempre tendrá un valor, por lo que es difícil desactivarlo ya que combineLatest
siempre tiene los últimos valores de cada observable en el argumento. Pero algo así debería ponerte en la dirección correcta.
Preguntas relacionadas
Nuevas preguntas
angular
Preguntas sobre Angular (que no debe confundirse con AngularJS), el marco web de Google. Use esta etiqueta para preguntas angulares que no son específicas de una versión individual. Para el marco web anterior de AngularJS (1.x), use la etiqueta angularjs.