头图

The official documentation of TakeUntil explains this operator as:

Emit values until provided observable emits.

That is, it can be assigned to another Observable that acts as an anchor. When the anchored Observable emits values, the original Observable stops emitting values and enters the complete operation.

See a practical example:

 import { interval, timer } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

//emit value every 1s
const source = interval(1000);
//after 5 seconds, emit value
const timer$ = timer(5000);
//when timer emits after 5s, complete source
const example = source.pipe(takeUntil(timer$));
//output: 0,1,2,3
const subscribe = example.subscribe(val => console.log(val));

The source Observable emits a sequence of integers starting at 0 and incrementing by 1 every 1-second interval.

We constructed a timer Observable with a timeout interval of 5 seconds, that is, at the fifth second, the Observable will emit a value. This timer Observable is passed into takeUntil as a notification Observable, and after five seconds, the source Observable will stop emitting integers.

Finally, the output of the above program execution: print 0 to 4 within 4 seconds, and then end.

another example:

 const interval = interval(1000);
const clicks = fromEvent(document, 'click');
const result = interval.pipe(takeUntil(clicks));
result.subscribe(x => console.log(x));

In this example, interval is used as the original Observable, and clicks is used as the notification Observable. The expression of the whole program is that an integer sequence incremented by 1 is printed every 1 second, until a click event occurs on the page, and the original interval Observable terminates.

See another example:

 // RxJS v6+
import { interval } from 'rxjs/observable/interval';
import { takeUntil, filter, scan, map, withLatestFrom } from 'rxjs/operators';

//emit value every 1s
const source = interval(1000);
//is number even?
const isEven = val => val % 2 === 0;
//only allow values that are even
const evenSource = source.pipe(filter(isEven));
//keep a running total of the number of even numbers out
const evenNumberCount = evenSource.pipe(scan((acc, _) => acc + 1, 0));
//do not emit until 5 even numbers have been emitted
const fiveEvenNumbers = evenNumberCount.pipe(filter(val => val > 5));

const example = evenSource.pipe(
  //also give me the current even number count for display
  withLatestFrom(evenNumberCount),
  map(([val, count]) => `Even number (${count}) : ${val}`),
  //when five even numbers have been emitted, complete source observable
  takeUntil(fiveEvenNumbers)
);
/*
    Even number (1) : 0,
  Even number (2) : 2
    Even number (3) : 4
    Even number (4) : 6
    Even number (5) : 8
*/
const subscribe = example.subscribe(val => console.log(val));

Let's analyze the logic of this example line by line:

 const evenSource = source.pipe(filter(isEven));

Produces an Observable that emits an even number every 1 second.

 const evenNumberCount = evenSource.pipe(scan((acc, _) => acc + 1, 0));

Accumulate the number of generated even numbers.

 const fiveEvenNumbers = evenNumberCount.pipe(filter(val => val > 5));

When the generated even number is greater than 5, the value is emitted. This Observable is used as the notification Observable of takeUntil.

 const example = evenSource.pipe(
  //also give me the current even number count for display
  withLatestFrom(evenNumberCount),
  map(([val, count]) => `Even number (${count}) : ${val}`),
  //when five even numbers have been emitted, complete source observable
  takeUntil(fiveEvenNumbers)
);
  1. Using eventSource and eventNumberCount, connect two Observables by withLatestFrom , so that in the map Operator, you can print out the current even value and the total even number at the same time. Passing in an Observable that emits values only when the total number of even numbers is greater than 5 can be achieved by takingUntil. After the total number of even numbers is greater than 5, the interval stops sending values.

The final execution effect:


注销
1k 声望1.6k 粉丝

invalid