DEV Community

Cover image for Debounced Aggregated (Buffered) Actions with RxJS 6 or How to stop making your users wait
Lucca Sanwald
Lucca Sanwald

Posted on

Debounced Aggregated (Buffered) Actions with RxJS 6 or How to stop making your users wait

TLDR;

Full Codesandbox Example

// (1) Add products on click
const AddProductSubject = new Subject(); 
const onClick = (event, product) => {
    AddProductSubject.next(product); 
};

// (2) Create debounce Observable as notifier for buffer
const debounceAddProduct$ = AddProductSubject.pipe(debounceTime(1500)); 

// (3) Buffer values until notifier emits a value
const AddProduct$ = AddProductSubject.pipe(
    buffer(debounceAddProduct$)
); 

// (4) Receive results
const AddProduct$Subscriber = AddProduct$.subscribe(result => {
    console.log("subscriber", result);
    saveSelection(); // triggers the loading screen
}, console.error); 
Enter fullscreen mode Exit fullscreen mode

What will I learn?

Sometimes, you don't want to react to a users input immediately and instead wait until he's finished multiple interactions before you save their progress. Find out how to buffer these interactions with RxJS 6.

How does it help?

This can make the difference between a tedious user experience. Where you're forced to wait for every single action to be completed. Demo

Negative Example - Non Debounced

And a pleasant user experience. Where the application only saves if you have stopped making actions for a certain timespan. Demo

Positive Example - Debounced

How does it work?

(1) Create a new Subject to be able to emit and receive values.
Push selected Products into the AddProductSubject whenever the onClick function is called. (in this case; whenever someone clicks on a product)

const AddProductSubject = new Subject(); 
const onClick = (event, product) => {
    AddProductSubject.next(product); 
};
Enter fullscreen mode Exit fullscreen mode

(2) Create the debounceAddProduct$ Observable that only emits a value if no additional values have been added to the AddProductSubject for 1500ms.

const debounceAddProduct$ = AddProductSubject.pipe(debounceTime(1500)); 
Enter fullscreen mode Exit fullscreen mode

(3) Create the AddProduct$ Observable, which buffers any emitted values until debounceAddProduct$ emits a value and therefore closes the buffer.

const AddProduct$ = AddProductSubject.pipe(
    buffer(debounceAddProduct$)
);
Enter fullscreen mode Exit fullscreen mode

(4) Subscribe to the AddProduct$ Observable and receive the buffered values, whenever the user has stopped selecting products for at least 1500ms

const AddProduct$Subscriber = AddProduct$.subscribe(result => {
    console.log("subscriber", result);
    saveSelection(); // triggers the loading screen
}, console.error); 
Enter fullscreen mode Exit fullscreen mode

Any ideas on how to improve this post? Tell me! I'm always grateful for valuable feedback ;)

Top comments (1)

Collapse
 
anduser96 profile image
Andrei Gatej

Very concise and useful! Thanks!