Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

109
Vistas
Implementar flujo con multidifusión que no completa el tema subyacente

Estoy implementando el caché usando BehaviorSubject y multicast . La secuencia devuelta de la memoria caché debe comenzar con una solicitud HTTP. También debería poder forzar la actualización del caché activando manualmente el next tema. El enfoque común con dos temas esbozado por Poul Kruijt es bien conocido y sugerido en todas partes. Mi idea es encontrar una manera de lograr lo siguiente utilizando solo un tema a lo largo del ciclo de vida de una transmisión.

Sería fácil de lograr con multidifusión como esta

 const cache = new BehaviorSubject(null); const shared = queryThatCompletes.pipe(multicast(cache)) as any; // sets up subscription, waits for connect shared.subscribe((values) => console.log(values)); // triggers http request shared.connect(); setTimeout(() => { // will only emit COMPLETE from subject shared.subscribe((values) => console.log(values)); }, 2000); // force refresh the cache cache.next();

pero dado que se completa el flujo de consulta HTTP, la segunda suscripción no obtiene ningún valor, solo la notificación COMPLETE del asunto. Este comportamiento se describe en detalle aquí .

La otra opción es pasar una función de fábrica en lugar de la instancia del sujeto como esta:

 const cache = ()=> new BehaviorSubject(null); const shared = queryThatCompletes.pipe(multicast(cache)) as any;

Esto volverá a crear el asunto, que se suscribirá a queryThatCompletes y volverá a activar la solicitud HTTP. Pero las desventajas son la necesidad de llamar a la connect varias veces y las consultas redundantes.

 const cache = () => new BehaviorSubject(null); const shared = queryThatCompletes.pipe(multicast(cache)) as any; // sets up subscription, waits for connect shared.subscribe((values) => console.log(values)); // triggers http request shared.connect(); setTimeout(() => { // sets up subscription, waits for connect shared.subscribe((values) => console.log(values)); // triggers http request shared.connect(); }, 2000);

Así que simplemente implementé el flujo HTTP que no se completa solo y lo uso así:

 const queryOnceButDontComplete = new Observable((observer) => { fetch('https://jsonplaceholder.typicode.com/todos/1') .then(response => response.json()) .then(data => observer.next(data)); return () => {}; }); const cache = new BehaviorSubject(null); const shared = queryOnceButDontComplete.pipe(multicast(cache)) as any; // sets up subscription, waits for connect shared.subscribe((values) => console.log(values)); // triggers http request shared.connect(); setTimeout(() => { // sets up subscription, waits for connect shared.subscribe((values) => console.log(values)); }, 2000);

Esto funciona, pero me pregunto si hay una manera de lograr lo que quiero sin el uso de observables personalizados. ¿Algunas ideas?

about 4 years ago · Santiago Gelvez
2 Respuestas
Responde la pregunta

0

Lo mejor sería usar un shareReplay(1) :

 const shared = queryThatCompletes.pipe(shareReplay(1)); // sets up subscription, waits for connect shared.subscribe((values) => console.log(values)); // triggers http request shared.connect(); setTimeout(() => { shared.subscribe((values) => console.log(values)); }, 2000);

No estoy del todo seguro de qué están haciendo la subscribe y la connect allí, pero si solo está devolviendo una llamada HttpClient get , entonces debe devolver el observable shared , y quien se suscriba primero, activará la solicitud http. No hay necesidad de connect . Cualquier suscripción posterior esperará a que finalice la solicitud o recibirá el último valor emitido del observable.


Según su comentario, envolvamos esto en un servicio (no probado):

 @Injectable() SomeDataService { readonly refresh$ = new BehaviorSubject(undefined); readonly get$ = this.httpClient.get(/*url here*/); readonly shared$ = this.refresh$.pipe( switchMap(() => this.get$), shareReplay(1) ); constructor(private httpClient: HttpClient) {} getData(): Observable<unknown> { return this.shared$; } refreshData(): void { this.refresh$.next(); } }

¿Esto tiene sentido? Básicamente, comienza con un tema de actualización, que se asigna a la llamada de red real. En el primer getData() , se activa la solicitud de red. Cualquier llamada a getData() después de eso obtendrá el valor almacenado en caché. Llamar a refreshData actualizará los datos de cualquier suscripción

about 4 years ago · Santiago Gelvez Denunciar

0

Hice un enfoque funcional que creo que es mucho más simple, usa dos observables refresh $ y el observable deseado, espero que esta solución pueda darle algunas ideas.

 const makeRestartableCahcedObservable = (ob:Observable<any>)=>{ const refresh$ = new BehaviorSubject(null) return [ refresh$.pipe( switchMap(()=>ob), shareReplay(1) ), ()=>refresh$.next(null) ] } const [ob, refreshFun] = makeRestartableCahcedObservable(of('string')) ob.subscribe(console.log) setTimeout(()=>{refreshFun()}, 3000)

esto básicamente puede actualizar sus datos con una API mucho más simple, incluso puede envolverlos con un objeto para convertirlos en un proxy con función de actualización incluida

 const makeRestartableCahcedObservable = (ob:Observable<any>)=>{ const refresh$ = new BehaviorSubject(null) const wrappedOb$ = refresh$.pipe(switchMap(()=>ob),shareReplay(1)) return { subscribe:(...args)=>wrappedOb$.subscribe(...args), pipe:(...funs)=>wrappedOb$.pipe(...funs), refresh:()=>refresh$.next(null) } } const ob = makeRestartableCahcedObservable(of('string')) ob.subscribe(console.error) setTimeout(()=>{ob.refresh()}, 3000)
about 4 years ago · Santiago Gelvez Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda