Flattens a higher-order callbag into a lower-order callbag:
1linkfunction flatten<T>(src: Source<Source<T>>): Source<T>
1linkimport {
2link fromEvent, map, interval, flatten, subscribe, pipe
3link} from 'callbag-common';
4link
5linkconst button = document.querySelector('button');
6linkconst span = document.querySelector('span');
7link
8linkpipe(
9link fromEvent(button, 'click'),
10link map(() => interval(100)), // --> map each click to a new interval (higher-order callbag)
11link flatten, // --> flatten the higher-order callbag
12link map(i => i / 10),
13link subscribe(i => span.textContent = i)
14link)
☝️ In this example, we turn each click into a new interval. So we start with a callbag of click events, then transform it into a callbag of intervals. Since each interval is a callbag itself, we basically have a callbag of callbags, which is a higher-order callbag.
flatten()
subscribes to the latest callbag emitted from the source. When a new callbag is emitted,
it will cancel the subscription to the previous one and subscribe to the new one.
👉 A commonly used higher-order callbag pattern is mapping user input to requests (which are callbags themselves).
It is common to use flatten()
in this pattern:
1linkimport {
2link fromPromise, fromEvent, flatten, subscribe, pipe, map,
3link} from 'callbag-common';
4link
5linkconst input = document.querySelector('input');
6linkconst button = document.querySelector('button');
7linkconst span = document.querySelector('span');
8link
9linkconst getRepo = async (repo) => {
10link try {
11link const res = await fetch('https://api.github.com/repos/' + repo);
12link return await res.json();
13link } catch {}
14link}
15link
16linkpipe(
17link fromEvent(button, 'click'),
18link map(() => fromPromise(getRepo(input.value))),
19link flatten,
20link map(repo => repo?.stargazers_count || '??'),
21link subscribe(count => span.textContent = count)
22link);