-
ES Streams
https://streams.spec.whatwg.org/ -
Reactive extensions
-
ES Observables
https://github.com/tc39/proposal-observable
-
-
Functional reactive programming
-
Functional reactive programming (FRP) is a programming paradigm for reactive programming (asynchronous dataflow programming) using the building blocks of functional programming (e.g. map, reduce, filter).
aiming to simplify these problems by explicitly modeling time.
-
-
ES Iterators
http://exploringjs.com/es6/ch_iteration.html-
http://exploringjs.com/es6/ch_iteration.html#sec_iterability
-
interface Iterable { [Symbol.iterator]() : Iterator; } interface Iterator { next() : IteratorResult; } interface IteratorResult { value: any; done: boolean; }
-
Data consumers: JavaScript has language constructs that consume data. For example, for-of loops over values and the spread operator (...) inserts values into Arrays or function calls.
ES6 introduces the interface Iterable. Data consumers use it, data sources implement it
Iterable and iterators are part of a so-called protocol (interfaces plus rules for using them) for iteration. A key characteristic of this protocol is that it is sequential: the iterator returns values one at a time. That means that if an iterable data structure is non-linear (such as a tree), iteration will linearize it.
-
-
-
ES Async Iterators
https://github.com/tc39/proposal-async-iteration -
ES Generators
http://exploringjs.com/es6/ch_generators.html-
Implementing iterables via generators
- Iterable combinators (e.g.
take()
) (Including Infinite iterables)
- Iterable combinators (e.g.
-
Generators for lazy evaluation
-
Generators as iterators (data production)
Lazy pull with generators works as follows. The three generators implementing steps 1–3 are chained as follows:
const CHARS = '2 apples and 5 oranges.'; const CHAIN2 = addNumbers(extractNumbers(tokenize(logAndYield(CHARS)))); [...CHAIN2];
Each of the chain members pulls data from a source and yields a sequence of items. Processing starts with tokenize whose source is the string CHARS.
function* logAndYield(iterable, prefix='') { for (const item of iterable) { console.log(prefix + item); yield item; } }
-
Generators as observers (data consumption)
const INPUT = '2 apples and 5 oranges.'; const CHAIN = tokenize(extractNumbers(addNumbers(logItems()))); send(INPUT, CHAIN);
/** * Pushes the items of `iterable` into `sink`, a generator. * It uses the generator method `next()` to do so. */ function send(iterable, sink) { for (const x of iterable) { sink.next(x); } sink.return(); // signal end of stream }
-
Generators as coroutines (cooperative multitasking)
-
run(countUp()); function run(generatorObject) { if (!generatorObject.next().done) { // Add a new task to the event queue setTimeout(function () { run(generatorObject); }, 1000); } } function* countUp(start = 0) { const counterSpan = document.querySelector('#counter'); while (true) { counterSpan.textContent = String(start); start++; yield; // pause } }
-
Communicating Sequential Processes (CSP)
import csp from 'js-csp'; csp.go(function* () { const element = document.querySelector('#uiElement1'); const channel = listen(element, 'mousemove'); while (true) { const event = yield csp.take(channel); const x = event.layerX || event.clientX; const y = event.layerY || event.clientY; element.textContent = `${x}, ${y}`; } }); function listen(element, type) { const channel = csp.chan(); element.addEventListener(type, event => { csp.putAsync(channel, event); }); return channel; }
-
-
-
-
ES Callbags
-
ES flow
callbacks -> promises -> generators -> async/await
-
https://github.com/whatwg/streams/blob/master/FAQ.md
Observables/EventTarget are specifically designed for multi-consumer scenarios, and have no support for backpressure.
Observables and readable streams both share the semantic of "zero or more chunks, followed by either an error or done signal". But beyond that, they are not very comparable.
- https://github.com/whatwg/streams/blob/master/FAQ.md
readable streams are a specialized type of async iterable optimized for things like off-main-thread data transfer and precise backpressure signaling