24 Jul 2024
5 min

takeWhile – RxJS Reference

takeWhile

takeWhile passes values from the source observable to the observer (mirroring) as long as the function known as the predicate returns true. The predicate function is passed as an argument to takeWhile. The operator subscribes to the source observable and begins mirroring the source Observable.

On each value takeWhile executes the predicate function passing the value as an argument and checks the returning value. If the value is true, it passes the value down to the observer, otherwise it completes the stream by unsubscribing from the source and passing the complete notification to the observer.

Besides the predicate function takeWhile takes the second parameter that defines whether it should pass the value to the observer or ignore it when the predicate function returns false.

Note, that if you only need to take a specific number of values from the source observable, you should use take operator.

takeWhile operator works in the following way:

  1. Subscribe to a source observable
  2. When a new value arrives from a source observable, execute the predicate function
  3. If the function returns truthy value, send the value to the observer
  4. If the function return falsy value, send the value to the observer if the operator is configured to be inclusive, unsubscribe from the source observable and send the complete notification to the observer
  5. Once the source observable completes, send the complete notification to the observer
  6. If the source observable throws an error, send the error notification to the observer

Usage

takeWhile can be used to destroy the chain and release resources once a certain value gets through. For example, you subscribe to the mousemove event when a mouse enters a box and want to unsubscribe when it leaves the box.

Here’s how you would do it with takeWhile:

const box = createBox();

fromEvent(box, 'mouseenter').pipe(
   exhaustMap(() => {
       // we're only interested in the mousemove event
       // as long as we're inside the box
       // once we leave the box, remove the listeners
       return fromEvent(box, 'mousemove').pipe(
           takeWhile((event: MouseEvent) => {
               return isEventInElement(
                   box.getClientRects(),
                   event.clientX,
                   event.clientY
               );
           })
       );
   })
).subscribe();

function isEventInElement(rect, clientX, clientY) {
   if (clientX < rect.left || clientX >= rect.right) return false;
   if (clientY < rect.top || clientY >= rect.bottom) return false;
   return true;
}

function createBox() {
   const box = document.createElement('div');

   box.style.backgroundColor = 'blue';
   box.style.position = 'fixed';
   box.style.top = '100px';
   box.style.left = '400px';
   box.style.width = '300px';
   box.style.height = '300px';

   document.body.appendChild(box);

   return box;
}

Playground

Additional resources

See also

Frequently asked questions

How does takeWhile work in RxJS?

takeWhile() subscribes to the source observable and passes each value downstream while the predicate function returns a truthy value. On each value it runs the predicate with that value as an argument. When the predicate returns a falsy value, it unsubscribes from the source and sends the complete notification to the observer. If the source completes on its own, the complete notification is forwarded as well.

What is the difference between take and takeWhile in RxJS?

Use take(n) when you need a fixed number of values, and takeWhile() when the stopping point depends on the values themselves. takeWhile() takes a predicate function that is evaluated for every emitted value, so the stream ends as soon as the condition fails rather than after a set count.

What does the inclusive parameter do in takeWhile?

The second argument of takeWhile() is an inclusive flag that controls the value that makes the predicate return false. By default that value is not passed to the observer. When inclusive is set, the failing value is still sent downstream before the operator unsubscribes from the source and completes the stream.

How do I unsubscribe from mousemove when the mouse leaves an element in RxJS?

Wrap fromEvent(box, 'mousemove') in takeWhile() inside an inner observable, for example within exhaustMap() applied to fromEvent(box, 'mouseenter'). The predicate checks the event's clientX and clientY against box.getClientRects(). Once the pointer leaves the box, the predicate returns false, takeWhile() unsubscribes from the source, and the mousemove listener is removed.

Does takeWhile forward errors from the source observable?

Yes. If the source observable throws an error, takeWhile() sends the error notification to the observer instead of completing silently. Handle it with an error callback in subscribe() or with an error-handling operator placed in the pipe, since the operator does not catch errors itself.

Share this post

Sign up for our newsletter

Stay up-to-date with the trends and be a part of a thriving community.