Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

123
Visualizações
Mantenga observable conectado incluso sin suscriptores

EDIT 2: lo que funcionó aún mejor fue shareReplay(1) , como se indica en la actualización de la respuesta de @karser .


EDIT 1: Lo que terminó funcionando mejor fue esto:

 @Injectable() export class MyGlobalService { private resource$; private resource$Connected; constructor(private http: Http) { this.resource$Connected = false; this.resource$ = this.http .get('/api/resource') .map((res: Response) => res.json()) .publishReplay(1); } getResource(): Observable<any> { if (!this.resource$Connected) { this.resource$.connect(); this.resource$Connected = true; } return this.resource$; } }

Solo realiza la llamada AJAX una vez y no llama hasta que algún consumidor requiera el recurso.


PREGUNTA ORIGINAL:

Estoy tratando de almacenar en caché una llamada HTTP angular y multidifundir el resultado más reciente a todos los suscriptores actuales y futuros. Los resultados de ajax no cambiarán durante la vida útil de la aplicación, por lo que no quiero hacer llamadas adicionales para un recurso que ya tengo. Por lo tanto, quiero que continúe "conectado" incluso cuando todos los suscriptores se den de baja. es posible?

Lo que probé inicialmente fue esto:

 // in a global service getResource(): Observable<any> { return this.http .get('/api/resource') .map((res: Response) => res.json()) .publishLast() .refCount(); }

Esto funciona bien para varias canalizaciones async en el mismo componente, pero si ese componente se destruye (y, por lo tanto, refCount pasa a 0), la solicitud HTTP se repetirá en una instancia posterior del componente.

Para combatir esto, comencé a almacenar manualmente en caché los resultados:

 resourceResults: any; getResource(): Observable<any> { if (resourceResults) { return Observable.of(this.resourceResults); } return this.http .get('/api/resource') .map((res: Response) => res.json()) .do(x => this.resourceResults = x) .publishLast() .refCount(); }

Esto funciona bien, pero siento que hay una forma más rx de hacerlo.

Intenté usar connect() , pero parece tener el mismo problema que mi primer ejemplo. Una vez que todos los suscriptores se han dado de baja, el uso de connect() hace que la solicitud HTTP vuelva a ocurrir

 resource$ = this.http .get('/api/resource') .map((res: Response) => res.json()) .publishLast() .refCount(); getResource(): Observable<any> { this.resource$.connect(); return this.resource$; }

¿Algunas ideas?

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

publicarReproducir/conectar funciona. Aquí está el plunker de trabajo :

 import {Injectable} from '@angular/core'; import {Http, Response} from '@angular/http'; import {Observable} from "rxjs/Observable"; @Injectable() export class YourService { resource:Observable<any>; constructor(private http: Http) { this.resource = this.http.get('https://api.github.com/users/karser') .map((res: Response) => res.json()) .do(res => console.log('response', res)) .publishReplay(1); this.resource.connect(); } }

La salida:

 Subscribing response Object {login: "karser", id: 1675033…} Unscibscribed Subscribing once again

ACTUALIZACIÓN: RxJS 5.4 tiene el operador shareReplay que aparentemente hace lo mismo. Ver el plunkr actualizado

 this.http.get('https://api.github.com/users/karser') .map((res: Response) => res.json()) .shareReplay(1);

De la solicitud de extracción:

shareReplay devuelve un observable que es la fuente multidifundida sobre un ReplaySubject . Ese tema de reproducción se recicla en caso de error de la fuente, pero no al completar la fuente. Esto hace que shareReplay sea ideal para manejar cosas como almacenar en caché los resultados de AJAX, ya que se puede volver a intentar. Su comportamiento de repetición, sin embargo, difiere de compartir en que no repetirá la fuente observable, sino que repetirá los valores de la fuente observable.

over 4 years ago · Santiago Trujillo Relatório

0

En primer lugar, si desea compartir esta respuesta durante toda la vida útil de la aplicación, debe colocarla en un servicio y asegurarse de que todos sus componentes compartan la misma instancia.

En teoría, podría hacer que la fuente Observable nunca se complete. Para ser más precisos, podría hacer que la cadena nunca propague la señal completa, pero esto no se recomienda y podría generar un comportamiento inesperado si intentara usar este Observable con operadores como forkJoin() o toArray() y cualquier similar que requiera el fuente Observable para completar correctamente.

En su lugar, puede usar publishReplay(1) para mantener el último valor emitido por el Observable de origen, refCount() para mantener una suscripción única al Observable de origen mientras se consulta el caché y luego take(1) para aceptar solo un valor y completar .

 const cache = this.http.get('/api/resource') .map((res: Response) => res.json()) .publishReplay(1) .refCount() .take(1);

Por lo tanto, puede suscribirse a varios observadores a la vez y solo se realizará una solicitud HTTP. Luego, cualquier suscripción posterior llegará a .publishReplay(1) que ya tiene un valor en caché que se propaga de inmediato y take(1) completa la cadena de inmediato. Por lo tanto, no habrá suscripción a this.http.get('/api/resource') y, por lo tanto, no se realizará ninguna solicitud.

over 4 years ago · Santiago Trujillo Relatório

0

No utilice refCount. Cree un observable conectable manualmente, conéctese, suscríbase y ReplaySubject del conectable mantendrá el último valor publicado. Algo como eso:

 let obs$ = Rx.Observable.interval(5000) .multicast(new Rx.ReplaySubject(1)); obs$.connect(); // unsuscribe when service is destroyed??? let mainSubecription = obs$.subscribe(x=>console.log(x)); // create subscription (like async pipe) let subscription; setTimeout(()=> { subscription = obs$.subscribe(x=>console.log('second', x)); }, 15000); // remove subscription (like async pipe) setTimeout(()=> { subscription.unsubscribe(); }, 40000); // the main subscription still gets data
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda