программа состоит из прозы на естественном языке вперемежку с макроподстановками и кодом на языках программирования
Давайте изменим традиционные приоритеты в создании программ: вместо представления о нашей задаче как о создании инструкций «Что делать?» для компьютера сконцентрируемся на объяснении другим людям описаний нашего видения того, что под управлением программы должен делать компьютер.
— Дональд Кнут
Парадигма, ориентированная на потоки данных и распространение изменений.
Императивные программы могли бы работать над реактивными структурами данных.
Вероятно, наиболее естественный способ сделать это состоит в том, что вместо методов и полей, у объектов есть реакции, которые автоматически пересчитывают значения и другие реакции зависят от изменений этих значений.
Является наиболее естественным базисом для реализации реактивной архитектуры, хорошо сочетаясь с параллелизмом.
Conal Elliott and Paul Hudak
Fran is a collection of data types and functions for composing richly interactive, multimedia animations.
вести себя как b1 до возникновения события e, после этого вести себя как b2.
ReactiveX is more than an API, it's an idea and a breakthrough in programming. It has inspired several other APIs, frameworks, and even programming languages.
Set of libraries to compose asynchronous and event-based programs using observable collections and Array#extras style composition in JavaScript
Observable — это объект или функция, которая выдает последовательности данных во времени.
Observer — это объект или функция, которая знает, как обрабатывать последовательности данных.
Subscriber — это объект или функция, которая связывает Observable и Observer.
Operators — это функции, которыми можно преобразовывать данные между моментом, когда Observable их отправил, и моментом, когда подписчик их получил.
var observable = Rx.Observable.create(function (observer) {
observer.next(1);
observer.next(2);
observer.next(3);
setTimeout(() => {
observer.next(4);
observer.complete();
}, 1000);
});
window.onload = function() {
var button = document.querySelector('button');
var observable = Rx.Observable.fromEvent(button, 'click');
observable.subscribe((event) => {
console.log('Observable: ', event);
});
button.addEventListener('click', (event) => {
console.log('Event listener: ', event);
});
}
observable.subscribe(
(x) => console.log('got value ' + x),
(err) => console.error('something wrong occurred: ' + err),
() => console.log('done')
);
Producer (изготовитель) - это некоторый поток, который генерирует данные и передает их в observable.
const source = new Observable((observer) => {
const socket = new WebSocket('ws://someurl');
socket.addEventListener('message', (e) => observer.next(e));
return () => socket.close();
});
const socket = new WebSocket('ws://someurl');
const source = new Observable((observer) => {
socket.addEventListener('message', (e) => observer.next(e));
});
когда важен порядок вывода последовательностей.
const getPostOne$ = Rx.Observable.timer(3000).mapTo({id: 1});
const getPostTwo$ = Rx.Observable.timer(1000).mapTo({id: 2});
Rx.Observable
.concat(getPostOne$, getPostTwo$)
.subscribe(res => console.log(res));
аналог Promise.all()
const getPostOne$ = Rx.Observable.timer(1000).mapTo({id: 1});
const getPostTwo$ = Rx.Observable.timer(2000).mapTo({id: 2});
Rx.Observable
.forkJoin(getPostOne$, getPostTwo$)
.subscribe(res => console.log(res))
чтобы все элементы внутренние Observable порождали событие основного.
const post$ = Rx.Observable.of({id: 1});
const getPostInfo$ = Rx.Observable
.timer(3000).mapTo({title: "Post title"});
const posts$ = post$
.mergeMap(post => getPostInfo$)
.subscribe(res => console.log(res));
возвращает не только текущее значение, но в месте с ним и предыдущее значение последовательности
// Tracking the scroll delta
Rx.Observable
.fromEvent(document, 'scroll')
.map(e => window.pageYOffset)
.pairwise()
.subscribe(pair => console.log(pair)); // pair[1] - pair[0]