2. Push vs Pull и ленивый запуск
Два способа получить значение
Прежде чем глубже погружаться в RxJS, важно понять одну ключевую идею: кто решает, когда появится значение? Есть два варианта — Pull и Push.
Pull: потребитель тянет
Pull (по-русски — «тянуть») — это когда вы просите значение и получаете его прямо сейчас. Классический пример — обычная функция:
const value = getValue(); // вы сами выбрали момент
Здесь инициатива у потребителя. Источник пассивен и просто отдаёт значение, когда у него спросят.
Push: источник сам присылает
Push (по-русски — «толкать») — наоборот: источник сам решает, когда отправить значение. Подписчик просто ждёт. Это похоже на email — почтальон сам кладёт письма в ящик, когда они приходят.
Observable — это Push-система. Подписавшись, вы получаете значения тогда, когда их выдаст источник.
Ленивость Observable
Это правило настолько важное, что его стоит запомнить отдельно: Observable ничего не делает до подписки. Когда вы пишете new Observable(fn), функция fn просто сохраняется. Она запускается только в момент .subscribe().
Это очень отличается от Promise: Promise запускает работу в момент создания, даже если на него никто не подписан. Observable — наоборот: молчит, пока его не «включат».
Глоссарий
new Observable(fn)— ручное создание Observable.fn— функция-«рецепт», описывающая, что делать после подписки.subscriber— объект, который мы получаем внутри функции-рецепта. У него есть методnext(value), которым мы отправляем значения подписчику.
Что нужно сделать
- Внутри
new Observable(subscriber => { ... })первой строкой вызовитеconsole.log('Observable started'). Это подтвердит, что код «рецепта» сработал. - Следом вызовите
subscriber.next('Value')— это отправит строку'Value'подписчику. - Логи
Before subscribeиAfter subscribeуже есть. Не трогайте их — они помогут увидеть порядок. - Запустите код и проследите за порядком вывода:
Before subscribe → Observable started → Received: Value → After subscribe. Этот порядок доказывает, что Observable стартовал именно при подписке.
const { Observable } = Rx;
const stream$ = new Observable(subscriber => {
console.log('Observable started');
subscriber.next('Value');
});
console.log('Before subscribe');
stream$.subscribe(value => {
console.log('Received: ' + value);
});
console.log('After subscribe');