最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

angular - How to refresh and listen to the refreshed data inside one stream - Stack Overflow

programmeradmin4浏览0评论

The important part of my code looks somewhat like this:

data$:Observable = this.dataRefresh$.pipe(switchMap(() => 
  this.http.get('url')), shareReplay());
dataRefresh$:Subject = new Subject();

ngOnInit(){
  this.externalService.getExternalTrigger()
    .pipe(
      // TODO - trigger data refresh and switch to data$
      tap(data => this.doThings(data)))
    .subscribe();
}

refresh(){
  this.refreshData$.next();
}

I'm trying to get new data after external service notified that the server-side data has been altered. My problem is that I have a few places in an app that need this data so the sharedReplay. When im trying to make some more complicated flow like:

 combineLatest([
   of().pipe(tap(() => this.refresh)),
   this.data.pipe(skipUntil(this.refreshData$))
 ]).pipe(map(([,data]) => data));

it just gives me circular dependency error. Any ideas?

The important part of my code looks somewhat like this:

data$:Observable = this.dataRefresh$.pipe(switchMap(() => 
  this.http.get('url')), shareReplay());
dataRefresh$:Subject = new Subject();

ngOnInit(){
  this.externalService.getExternalTrigger()
    .pipe(
      // TODO - trigger data refresh and switch to data$
      tap(data => this.doThings(data)))
    .subscribe();
}

refresh(){
  this.refreshData$.next();
}

I'm trying to get new data after external service notified that the server-side data has been altered. My problem is that I have a few places in an app that need this data so the sharedReplay. When im trying to make some more complicated flow like:

 combineLatest([
   of().pipe(tap(() => this.refresh)),
   this.data.pipe(skipUntil(this.refreshData$))
 ]).pipe(map(([,data]) => data));

it just gives me circular dependency error. Any ideas?

Share Improve this question edited Mar 21 at 19:55 Naren Murali 60.3k5 gold badges44 silver badges77 bronze badges asked Mar 21 at 19:16 MirzMirz 335 bronze badges 2
  • the subject next call will refresh the API, what is the exact problem with the code above? – Naren Murali Commented Mar 21 at 19:22
  • I want to perform doThings() method using new data. But i need both to trigger the http call, and to listen to it's results – Mirz Commented Mar 21 at 19:25
Add a comment  | 

1 Answer 1

Reset to default 1

I have create a small demo of the situation, but replaced the service method with a subject instead.

The main part involves this code, where we convert the tap to a switchMap since we want to switch to data$ after doing some actions, we then create an instance of an observable and use this method to both trigger the subject using next and also get the results using an inner subscribe. To stop the observable on first emission, I use take(1) to end the inner subscribe.

ngOnInit() {
  this.getExternalTrigger$
    .pipe(
      // TODO - trigger data refresh and switch to data$
      switchMap((data: any) => this.doThings(data))
    )
    .subscribe(console.log);
}

doThings(data: any) {
  // doing things;
  console.log('doing things', data);
  return new Observable((obs) => {
    const sub = this.data$.pipe(take(1)).subscribe(obs);
    this.dataRefresh$.next();
    return () => sub.unsubscribe();
  });
}

Full Code:

import { Component, inject } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';
import { provideHttpClient, HttpClient } from '@angular/common/http';
import { Subject, Observable, switchMap, shareReplay, of, take } from 'rxjs';
@Component({
  selector: 'app-root',
  imports: [CommonModule],
  template: `
  {{data$ | async | json}}<br/>
    <button (click)="triggerFakeRefresh()"> triggerFakeRefresh</button>
  `,
})
export class App {
  http = inject(HttpClient);
  dataRefresh$: Subject<void> = new Subject();
  getExternalTrigger$: Subject<void> = new Subject(); // fake api
  data$: Observable<any> = this.dataRefresh$.pipe(
    switchMap(() =>
      this.http.get('https://jsonplaceholder.typicode/todos/1')
    ),
    shareReplay()
  );

  ngOnInit() {
    this.getExternalTrigger$
      .pipe(
        // TODO - trigger data refresh and switch to data$
        switchMap((data: any) => this.doThings(data))
      )
      .subscribe(console.log);
  }

  doThings(data: any) {
    // doing things;
    console.log('doing things', data);
    return new Observable((obs) => {
      const sub = this.data$.pipe(take(1)).subscribe(obs);
      this.dataRefresh$.next();
      return () => sub.unsubscribe();
    });
  }

  refresh() {
    this.dataRefresh$.next();
  }

  triggerFakeRefresh() {
    this.getExternalTrigger$.next();
  }
}

bootstrapApplication(App, {
  providers: [provideHttpClient()],
});

Stackblitz Demo

发布评论

评论列表(0)

  1. 暂无评论