简体   繁体   中英

TakeUntil with Checkbox Blocks Stream Even When Evaluation is True

I'm trying to use takeUntil to stop a stream once a checkbox is switched off. I'm in Angular so for now I'm just concatenating a sting on a class property, not worrying about concatenating results of observables yet.

this.checked$ is a BehaviorSubject that starts false and gets next ed when my checkbox is de/activated. That part is for sure working at least somewhat because below will start to display the dots. However, adding the (commented out below) takeUntil(this.checked$) results in no dots displaying at all.

const source$ = interval(250).pipe(mapTo("."));
this.checked$
.pipe(
  filter(c => {
    return c === true;
  }),
  switchMap(() => {
    console.log("switchMap");
    // return source$.pipe(takeUntil(this.checked$));
    return source$;
  })
)
.subscribe(data => {
  console.log("in subscribe", data, this.dots);
  this.dots += data;
});

What is incorrect about how I am using BehaviorSubject and takeUntil here?

Here is a full example is on StackBlitz .

Note that takeUntil emits values only until the first checked$ is emited, here are good examples. Because checked$ is a BehaviorSubject it emits the current value immediately when you subscribe to it, as a result takeUntil stops.

A solution might be to switch between source$ and an empty observable inside the switchMap, like:

const source$ = interval(250).pipe(mapTo("."));
this.checked$
  .pipe(
    switchMap(c => {
      console.log("switchMap");
      return c ? source$ : EMPTY;
    })
  )
  .subscribe(data => {
    console.log("in subscribe", data, this.dots);
    this.dots += data;
  });

StackBlitz example


You can also fix your original solution by skipping the first value of checked$ subject, but I recommend you the previous solution because it's simpler.

const source$ = interval(250).pipe(mapTo("."));
this.checked$
  .pipe(
    filter(c => {
      return c === true;
    }),
    switchMap(() => {
      console.log("switchMap");
   // return source$.pipe(takeUntil(this.checked$));
      return source$.pipe(takeUntil(this.checked$.pipe(skip(1))));
    })
  )
  .subscribe(data => {
    console.log("in subscribe", data, this.dots);
    this.dots += data;
  });

StackBlitz example


Another solution is to use Subject instead of BehaviorSubject . The difference is that the Subject doesn't hold current value and emits nothing when you subscribe to it. It emits only when next() is called. If you replace BehaviorSubject with Subject in your original solution, it will work as expected.

StackBlitz example

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