简体   繁体   中英

New Request in RxJs interval

I have an interval in my application that gets information from API every 2 minutes. This interval do 3 call at the same time, gets some list and do some stuff with it.

In this list, there are some items. I want to delete one item and then re-call the list (interval) to get the new list updated and show it (without wait the interval time, basically, refresh the call). But I don't know how. I tried to create a subject and with a .next ('') , call the interval again (with consequent errors, ofc). I think I'm missing something related to the operation of switchMap and polling .

    const created$ = this.collections.getMyCollections('created'); // returns Observable<Collection[]>
    const asigns$ = this.collections.getMyCollections('asigns');
    const groups$ = this.collections.getMyCollections('groups');

    /** Interval*/
    let pollInterval = 120000;
    let timer$ = timer(0, pollInterval);


    /** subscriptions */
    this.pollingSubscription  = timer$.pipe(switchMap(() => forkJoin(creates$, asigns$, groups$))).subscribe(([CREATED, ASIGNS, GROUPS]) => {
        /** Some stuff here*/
    });

Thanks in advance.

You could switch from forkJoin to a combineLatest of a BehaviorSubject:

const created$ = this.collections.getMyCollections("created"); // returns Observable<Collection[]>
const asigns$ = this.collections.getMyCollections("asigns");
const groups$ = this.collections.getMyCollections("groups");

const refresh$ = new BehaviorSubject<"created" | "asigns" | "groups" | "init">(
  "init"
);

/** Interval*/
let pollInterval = 120000;
let timer$ = timer(0, pollInterval);

/** subscriptions */
this.pollingSubscription = timer$
  .pipe(
    switchMap(() =>
      combineLatest(
        refresh$.pipe(
          filter(refreshId => refreshId === 'created' || refreshId === 'init'),
          switchMap(() => created$)
        ),
        refresh$.pipe(
          filter(refreshId => refreshId === 'asigns' || refreshId === 'init'),
          switchMap(() => asigns$)
        ),
        refresh$.pipe(
          filter(refreshId => refreshId === 'groups' || refreshId === 'init'),
          switchMap(() => groups$)
        )
      )
    )
  )
  .subscribe(([CREATED, ASIGNS, GROUPS]) => {
    /** Some stuff here*/
  });

The BehaviorSubject would emit 'init' upon subscription which would trigger the 3 observables in the combineLatest . As soon as you want to refresh one of the collections you can call:

this.refresh$.next('created');
// OR
this.refresh$.next('asigns');
// OR
this.refresh$.next('groups');

I didn't test this code, it's the general idea. I think you may have to rewrite the timer part a little bit to avoid having multiple subscribers over time.

My preference for forkJoin is the following pattern, which might help you if there's stuff you want to do after one of the forkJoin methods has emitted its value.

Each observable takes care of its own after effects in its own pipe rather than delegating to the subscribe body.

forkJoin([
  observable1.pipe(
    tap(res1 => this.res1 = res1)
  ),
  observable2.pipe(
    tap(res2 => this.res2 = res2),
    // run additional observable this could be conditional if you need it to be
    switchMap(() => observable2a.run()),
    tap(res2a => this.res2a = res2a)
  ),
  observable3.pipe(
    tap(res3 => this.res = res3)
  )
]).subscribe(() => {
  // clean subscribe body
  // do whatever you need to do now all observables have run  
});

The benefit of this is that it keeps your observable dependencies together, and prevents the subscribe body becoming a big mess.

It's a little unclear where the delete might take place in your code, but I think this pattern might help you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM