visit
Hey, RxJS streamers! 🙋♂️
Today we're going to review a small library that re-evaluates an expression based on updates in streams it uses.tl;dr: docs and package at 🔗
Let's boldly explore it!
import { timer } from 'rxjs';
import { computed, $ } from 'rxjs-autorun';
// timer would emit every second
const a = timer(0, 1_000);
// expression would concat every emission with a cake
const result = computed(() => $(a) + ' 🍰');
// now we should subscribe to the resulting stream
result.subscribe(x => console.log(x));
// > 0 🍰
// > 1 🍰
// > 2 🍰
// > …
Explanation: computed takes a function that uses some streams and re-evaluates it when those streams update. It returns an observable that you can manipulate further. And $(a) indicates that a is a stream and its updates should be listened to.
So technically this expression is equivalent to
a.pipe( map(x => x + '🍰') )
But let's keep discovering what else this tiny lib can do:import { timer, of } from 'rxjs';
import { delay } from 'rxjs/operators';
import { computed, $ } from 'rxjs-autorun';
const a = timer(0, 1_000); // get some monkeys
const b = of('🍌').pipe(delay(2_000)); // fetch some treats
const result = computed(() => '🐒 #' + $(a) + ' gets ' + $(b)); // mix
result.subscribe(x => console.log(x)); // listen to result stream
// ...2s gap...
// > 🐒 #1 gets 🍌
// > 🐒 #2 gets 🍌
// > 🐒 #3 gets 🍌
// > …
This expression is similar to
combineLatest(a, b).pipe( map(([x,y]) => x + y) )
Let's review another multiple streams example:import { Subject } from 'rxjs';
import { computed, $, _ } from 'rxjs-autorun';
const a = new Subject(); // neighbours
const b = new Subject(); // food
computed(() => $(a) + ' likes ' + _(b))
.subscribe(x => console.log(x));
a.next('🐈'); // nothing: b is still empty
b.next('🥛'); // > 🐈 likes 🥛
a.next('🐭'); // > 🐭 likes 🥛
b.next('🍕'); // nothing: _(b) doesn't trigger re-runs
a.next('🙋♂️'); // 🙋♂️ likes 🍕
Explanation:
_
function indicates that we need to take one value from a stream, but we don't want to recalculate our expression when this particular stream emits. So if an expression uses $(a)
and _(b)
— it would react only to updates.This also means that computed(() => _(a)) expression would emit one value and immediately complete.Okay, one really the last thing before we wrap-up:import { timer, of } from 'rxjs';
import { computed, $, _ } from 'rxjs-autorun';
const a = timer(0, 1_000);
const b = of('💧');
const c = of('❄');
const result = computed(() => $(a) % 2 ? _(b) : _(c));
result.subscribe(x => console.log(x));
Actually, this expression is somewhat similar to
Thank you for reading this article! Stay reactive and have a nice day 🙂
I want to thank for lengthy discussions of this idea, for giving it a try, and for collaborating with me on this! 🙏Also published at