Как работает оператор from в RxJS
Development | Комментировать запись
Оператор RxJS from используется для преобразования итерируемых данных в наблюдаемые объекты. Это свойство может быть особенно полезно, если вы хотите превратить типы передаваемых и совместно используемых данных в наблюдаемые последовательности или же если функция собирается получить наблюдаемый объект и воздействовать на него. Также оператор from можно использовать, если вам нужно применить оператор RxJS, который обычно недоступен для исходного типа данных.
К итерируемым типам, которые можно преобразовать в наблюдаемые объекты с помощью from, относятся массивы, карты, наборы, промисы, узлы DOM и функции-генераторы. Ниже мы рассмотрим примеры некоторых из этих типов.
Массивы и оператор from
Чаще всего оператор from используется для преобразования массива в наблюдаемый объект:
let myArr = ['🐦', '😺', '🐕', '🐊']; Rx.Observable .from(myArr) .filter(x => x !== '🐦') .map(x => `Hello ${x}!`) .subscribe(console.log); // Hello 😺! // Hello 🐕! // Hello 🐊!
Синхронные и асинхронные наблюдаемые объекты
По умолчанию оператор from возвращает синхронные наблюдаемые объекты:
let myArr = ['😺', '🐕', '🐊']; console.log('Before'); Rx.Observable .from(myArr) .map(x => `Hello ${x}!`) .subscribe(console.log); console.log('After'); // Before // Hello 😺! // Hello 🐕! // Hello 🐊! // After
Однако при необходимости их можно сделать асинхронными при помощи Rx.Scheduler.async:
let myArr = ['😺', '🐕', '🐊']; console.log('Before'); Rx.Observable .from(myArr, Rx.Scheduler.async) .map(x => `Hello ${x}!`) .subscribe(console.log); console.log('After'); // Before // After // Hello 😺! // Hello 🐕! // Hello 🐊!
Функции-генераторы и оператор from
Читайте также: Функции-генераторы в JavaScript ES6/ES2015
Функции-генераторы относятся к итерируемым типам данных, потому их легко можно преобразовать в наблюдаемый объект при помощи оператора from:
function* generateUnique() { let num = 0; while (true) { yield num++; } } Rx.Observable.from(generateUnique()) .take(3) .subscribe(console.log); // 0 // 1 // 2
Примечание: Здесь мы используем оператор take для завершения наблюдаемого объекта после указанного количества значений. В противном случае у нас получился бы бесконечный наблюдаемый объект и при подписке случилась бы ошибка.
А вот немного более сложный пример, в котором также используется оператор zip (для объединения значений нескольких наблюдаемых объектов):
function* generateName() { yield 'Cat'; yield 'Dog'; yield 'Bird'; return; } function* generateEmoji() { yield '😺'; yield '🐕'; yield '🐦'; return; } function* generateSound() { yield 'Meow'; yield 'Woof'; yield 'Tweet'; return; } const names = Rx.Observable.from(generateName()); const emojis = Rx.Observable.from(generateEmoji()); const sounds = Rx.Observable.from(generateSound()); const combined = Rx.Observable.zip(names, emojis, sounds, (name, emoji, sound) => { return `The ${name} ${emoji} goes ${sound.toUpperCase()}`; }) .subscribe(console.log); // The Cat 😺 goes MEOW // The Dog 🐕 goes WOOF // The Bird 🐦 goes TWEET
Примечание: Обратите внимание, что здесь для объединения генераторов и наблюдаемых объектов также используется оператор spawn, но в настоящее время в RxJS 5+ этот оператор недоступен.
Промисы и оператор from
Промисы также можно легко преобразовать в асинхронные наблюдаемые объекты, которые будут обертывать значения resolve или reject:
const myPromise = new Promise((resolve, reject) => { setTimeout(() => { resolve('Hello'); }, 2000); }); Rx.Observable .from(myPromise) .subscribe(x => console.log(x, ' World!')); // Hello World! (after 2 seconds)
Узлы DOM
Давайте посмотрим на следующий простой пример, в котором набор из 3 узлов DOM преобразуется в наблюдаемый объект и сопоставляется для извлечения только textContent:
<h2>Hey,</h2> <h2>Hello</h2> <h2>Alligator!</h2> <script> const h2s = document.querySelectorAll('h2'); Rx.Observable.from(h2s) .map(h2 => h2.textContent) .subscribe(console.log); // Hey, // Hello // Alligator! </script>
Кратко о строках
Строки тоже можно итерировать, следовательно, с ними можно использовать оператор from, но при этом каждый символ в строке будет отдельным значением:
Rx.Observable .from('Hi!') .subscribe(console.log); // H // i // !
Если вы хотите преобразовать строку в единое значение, вам нужно использовать оператор of, а не from:
Rx.Observable .of('Hi!') .subscribe(console.log); // Hi!Tags: RxJS