Предварительные требования: было бы полезно знакомство с библиотеками FRP, такими как RxJS.
Обычно у наблюдателя есть три метода - следующий, ошибка, завершено. Простой наблюдатель может выглядеть так -
const observer = { next(value) { console.log(`next -> ${value}`) }, error(err) { console.log('error') }, complete() { console.log('completed') } }
Наблюдаемое могло бы выглядеть примерно так -
function observable(observer) { for(var i = 0; i <= 10; i++) { observer.next(i) } observer.error() observer.complete() }
Этот наблюдаемый испускает последовательность чисел от 0 до 10, затем выдает ошибку и, наконец, выдает полное. Это нереальная реализация. В реальном мире у нас есть концепция SafeObservers, в которой наблюдаемое перестает наблюдаться в момент выдачи либо ошибки, либо завершения. Но цель этой статьи не в том, чтобы углубиться в реальных наблюдателей и наблюдаемых, а в том, чтобы показать вам, как генератор ES6 можно использовать в качестве наблюдателя.
Недостаточно наличия наблюдаемого и наблюдателя - наблюдатель должен наблюдать наблюдаемое. Это так просто, как -
observable(observer)
В результате -
"next -> 0" "next -> 1" "next -> 2" "next -> 3" "next -> 4" "next -> 5" "next -> 6" "next -> 7" "next -> 8" "next -> 9" "next -> 10" "error" "completed"
Как я уже упоминал выше, у наблюдателя есть три метода - next, error и close. Если вы посмотрите на итератор ES6 (который обычно создается путем вызова генератора), он также имеет три метода - next, throw и return. Итак, вы можете создать генератор, который возвращает итератор, подобный этому -
function* observerGenerator() { try { while(true) { let value = yield console.log(`next -> ${value}`) } } catch (err) { console.log('error') } console.log('completed') }
Затем мы создаем служебную функцию, которая преобразует наш итератор в наблюдателя -
function createObserver(iterator) { return { next(value) { iterator.next(value) }, error(err) { iterator.throw(err) }, complete() { iterator.return() } } }
Обратите внимание на соответствие между методами наблюдателя и методами итератора -
| Observer | Iterator | ----------------------------------- | next | next | | error | throw | | complete | return |
Чтобы начать наблюдать наблюдаемое -
observable(createObserver(observerGenerator()))
И результат такой же, как и раньше. Фрагменты кода доступны в виде здесь.