предисловие
с дляRxJS
Заинтересовавшись этой технологией, автор провел несколько дней, изучая эту технологию, и завершил написание этой статьи пакетом лайчи, что непросто. Однако именно в этот период обучения я обнаружил, что эта технология может в определенной степени решить некоторые болевые точки, с которыми я сталкивался в своей повседневной работе, и у меня появилось желание немедленно применить ее к моим новым проектам. потока данных для управления данными в больших проектах может принести очень элегантный опыт программирования.
Если вы найдете это полезным после прочтения, я надеюсь поставить лайк автору 😘
концепция
RxJS
даReactive Extensions for JavaScript
сокращение отReactive Extensions
, представляет собой наблюдаемый поток данных, основанный наStream
Библиотека приложений асинхронного программирования, сочетающая шаблон наблюдателя и шаблон итератора.RxJS
даReactive
Extensions
существуетJavaScript
реализация выше.
Уведомление! следует
React
Не беда, автор изначально видел это какReact.js
Аббревиатура от (позор!!!)
Для незнакомых технологий наша общая идея состоит в том, чтобы открыть Baidu (google), поискать, а затем проверить официальные документы, или найти информацию, которая может понять эту технологию, из разрозненных блогов. Но во многих случаях действительно сложно понять все тонкости технологии всего по нескольким словам.
Эта статья с точки зрения обучения анализу ценности технологии и преимуществ, которые должен дать наш существующий проект.
задний план
С точки зрения разработчика, для любой технологии часто говорят о следующих моментах:
- Сценарий применения?
- Как приземлиться?
- Насколько легко начать?
- Зачем тебе это? Какую проблему он решает?
Ввиду вышеуказанных проблем мы можем анализировать от более мелкого к более глубокому.RxJS
родственные понятия.
Сценарий применения?
Допустим, у нас есть такое требование:
После того, как мы загрузим большой файл, нам нужно отслеживать его прогресс в режиме реального времени и прекращать мониторинг, когда прогресс достигает 100.
Для общей практики мы можем использовать короткий опрос для его реализации.При инкапсуляции асинхронных запросов, если мы используемPromise
метод, то наш общий подход может заключаться в том, чтобы написать метод для опроса, получить возвращаемое значение для обработки, если прогресс не завершен, то снова вызвать метод через определенную временную задержку, а при возникновении ошибки нам нужно отловить ошибка и обрабатывать ее.
Очевидно, что такой способ обработки, несомненно, в определенной степени влечет за собой определенную стоимость разработки и обслуживания для разработчиков, потому что этот процесс больше похож на то, что мы наблюдаем за событием, которое будет запускаться много раз и позволять мне воспринимать его, не только это, но и Чтобы иметь возможность отписаться,Promise
То, как вы справляетесь с такими вещами, на самом деле недружелюбно, иRxJS
Управление асинхронными потоками данных больше соответствует этой парадигме.
Цитирую Вас Да:
лично я склоняюсь
Rx
место для использованияRx
, но не обязательноRx for everything
. Подходящим примером является сервер обмена мгновенными сообщениями, такой как множество потоков,Rx
высокоуровневая обработка и, наконец,view
слой очень четкийObservable
,ноview
Сам слой все еще может использовать существующую парадигму для обработки пользовательских событий.
Как приземлиться?
Для существующих проектов то, как совместить с реальностью и обеспечить стабильность исходного проекта, действительно является приоритетом, который мы должны рассмотреть, ведь если какая-либо технология не может быть применена на практике, она неизбежно принесет нам относительно ограниченные выгоды.
Вот если вы пользователь
Angular
Разработчики, возможно, вам следует знатьAngular
Глубоко интегрированныйRxjs
, пока вы используетеAngular
Framework, вы неизбежно столкнетесь со знаниями, связанными с RxJ.
В некоторых сценариях, где требуется более точный контроль событий, например, мы хотим прослушивать события кликов, но больше не прослушиваем после трех кликов.
Затем импортируйте в это времяRxJS
Разработка функции очень удобна и эффективна, что позволяет избавиться от необходимости отслеживать события и записывать состояние кликов, а также избавляться от некоторой логической психологической нагрузки по отмене мониторинга.
Вы также можете представить свой большой проектRxJS
Выполнение унифицированных спецификаций управления потоком данных, конечно же, не дает этому непригодномуRxJS
Концепция сцены навязана, поэтому фактический эффект может быть неочевидным.
Насколько легко начать?
Если вы разработчик с небольшим опытомJavaScript
разработчик, то через несколько минут вы сможетеRxJS
Применяется к какой-то простой практике.
Зачем тебе это? Какую проблему он решает?
Если вы пользовательJavaScript
Сталкиваясь с обработкой многочисленных событий и сложным анализом и преобразованием данных, легко ли разработчикам написать очень неэффективный код или раздутые суждения и большое количество грязных логических операторов?
Мало того, вJavaScript
В мире , с точки зрения многих сценариев, имеющих дело с асинхронными событиями, слово «проблема», кажется, легко упоминается.JS
Внимательнее изучите историю обработки асинхронных событий.RxJS
принесенное значение.
Функция обратного вызова Times (обратный вызов)
используемые сцены:
- обратный вызов события
-
Ajax
просить Node API
-
setTimeout
,setInterval
Дождитесь обратного вызова асинхронного события
В приведенном выше сценарии наш первоначальный метод обработки заключается в передаче функции обратного вызова при вызове функции и выполнении функции обратного вызова после завершения синхронного или асинхронного события. Можно сказать, что в большинстве простых сценариев, несомненно, очень удобно использовать функции обратного вызова, такие как несколько известных функций высшего порядка:
forEach
map
filter
[1, 2, 3].forEach(function (item, index) {
console.log(item, index);
})
То, как они используются, требует от нас только передачи функции обратного вызова для завершения пакетной обработки набора данных, что очень удобно и понятно.
Но в борьбе с сложным бизнесом мы все еще поддерживаем, если не отказаться от того, как не отказывайтесь от идеи использования цепной функции обратного вызова в следующих обстоятельствах:
fs.readFile('a.txt', 'utf-8', function(err, data) {
fs.readFile('b.txt', 'utf-8', function(err, data1) {
fs.readFile('c.txt', 'utf-8', function(err, data2) {
// ......
})
})
})
Конечно, как писатель, вы можете чувствовать, что это очень ясно, ах, ничего плохого. Но если точка его более сложной, если не одинаковая функция, позвоните ему, если каждое содержимое обратного вызова внутри оно очень сложно. Краткосрочный срок, чтобы он мог написать ясно, почему, для каких целей, но через месяц, три месяца, один год спустя, многие дела вы уверены, что вы можете получить оригинальный код оригинала это?
Вам не терпится найти запись о представлении? Какой идиот написал это?
shit
..., что за бред я написал.
В это время, столкнувшись с бедствием многих разработчиков回调地域
, наконец-то кто-то вышел на пользу человечеству...
Эпоха обещаний
Promise
Изначально было предложено сообществом (в конце концов, поскольку мы имеем дело со странными бизнес-кодами каждый день, мы не можем все время выдержать его с обратными вызовами), а затем официальный официальный сайтES6
Он добавлен к языковому стандарту и стандартизирован, так что мы можем изначальноnew
ОдинPromise
.
С точки зрения преимуществ,Promise
Он предлагает метод кодирования, отличный от функции обратного вызова. Он использует цепные вызовы, отбрасывает данные обратно по одному слою за раз и может выполнять унифицированный захват исключений. Это не похоже на использование функции обратного вызова для прямого взрыва, и это должно быть во многих один за другим в кодеtry catch
.
Без лишних слов, посмотрите на код!
function readData(filePath) {
return new Promise((resolve, reject) => {
fs.readFile(filePath, 'utf-8', (err, data) => {
if (err) reject(err);
resolve(data);
})
});
}
readData('a.txt').then(res => {
return readData('b.txt');
}).then(res => {
return readData('c.txt');
}).then(res => {
return readData('d.txt');
}).catch(err => {
console.log(err);
})
Напротив, такой способ написания будет больше соответствовать нашей обычной логике мышления, в таком порядке он заставляет людей выглядеть очень комфортно и более благоприятен для сопровождения кода.
преимущество:
- Если состояние изменится, оно больше не изменится, и вы можете получить тот же результат в любое время.
- Оптимизация обработки асинхронных событий, что делает запись более удобной.
недостаток:
- Не могу отменить
- Ошибка не может быть
try catch
(но вы можете использовать.catch
Способ) - когда в
pending
Невозможно узнать, на какой стадии он находится, когда он находится в состоянии
несмотря на то чтоPromise
Появление события в определенной степени повысило эффективность нашей обработки асинхронных событий, но когда нам нужно смешивать обработку с некоторыми синхронными событиями, нам часто приходится сталкиваться с некоторой не очень удобной миграцией кода. код, первоначально размещенный во внешнем слое. перейти кPromise
Внутренняя возможность гарантировать завершение асинхронного события перед продолжением выполнения.
Функция генератора
ES6
недавно представленныйGenerator
функция, которая может бытьyield
Ключевое слово приостанавливает поток выполнения функции, позволяя изменить поток выполнения, тем самым предоставляя решение для асинхронного программирования. Это также обычная функция по форме, но имеет несколько примечательных особенностей:
-
function
Между ключевым словом и названием функции стоит звездочка "*" (рекомендуется рядом сfunction
ключевое слово) - Использовать внутри функции
yield· 表达式,定义不同的内部状态 (可以有多个
выход`) - позвонить напрямую
Generator
Функция не выполняется и не возвращает результат операции, а возвращает объект обходчика (Iterator Object
) - Вызов объекта итератора
next
метод, траверсGenerator
Каждое состояние внутри функции
function* read(){
let a= yield '666';
console.log(a);
let b = yield 'ass';
console.log(b);
return 2
}
let it = read();
console.log(it.next()); // { value:'666',done:false }
console.log(it.next()); // { value:'ass',done:false }
console.log(it.next()); // { value:2,done:true }
console.log(it.next()); // { value: undefined, done: true }
С помощью этого режима записи мы можем свободно управлять механизмом выполнения функции и позволять функции выполняться, когда это необходимо, но для повседневных проектов этот метод записи недостаточно удобен и не может дать пользователям самое интуитивное ощущение.
async / await
Я считаю, что после многих вопросов на собеседовании все должны более-менее знать, что эта штука на самом деле является синтаксическим сахаром, а внутреннее заключается в том, чтобы поставитьGenerator
Функции и автоисполнителиco
В совокупности мы можем писать асинхронный код синхронным способом, что очень приятно.
Одно скажу, эта штука действительно проста в использовании.Если бы не совместимость, очень хочется использовать этот метод на большой площади.
Давайте посмотрим, как приятно писать код:
async readFileData() {
const data = await Promise.all([
'异步事件一',
'异步事件二',
'异步事件三'
]);
console.log(data);
}
Напишите его непосредственно как синхронный метод и не думайте о копировании и вставке кода внутри другой асинхронной функции, которая действительно кратка и ясна.
RxJS
Он используется так же, какPromise
Вроде как, но мощнее, чемPromise
Он намного мощнее, может не только управлять данными в виде потоков, но и имеет множество встроенных инструментов и методов, которые позволяют нам легко обрабатывать различные операции на уровне данных, делая наш код гладким как шелк.
Преимущество:
- Значительное уменьшение размера кода
- Улучшена читаемость кода
- хорошая обработка асинхронности
- Управление событиями, механизм планирования
- очень богатый оператор
- декларативный стиль программирования
function readData(filePath) {
return new Observable((observer) => {
fs.readFile(filePath, 'utf-8', (err, data) => {
if (err) observer.error(err);
observer.next(data);
})
});
}
Rx.Observable
.forkJoin(readData('a.txt'), readData('b.txt'), readData('c.txt'))
.subscribe(data => console.log(data));
Здесь показано толькоRxJS
Верхушка айсберга, которая может выражать энергию, есть много способов справиться с такого рода сценой.RxJS
Хорошо справляется с асинхронными потоками данных и имеет множество библиотечных функций. дляRxJS
он может конвертировать любойDom
событие илиPromise
Перевести вobservables
.
Предварительные знания
официально вступающийRxJS
Перед миром нам сначала нужно прояснить и понять несколько понятий:
- Реактивное программирование (
Reactive Programming
) - поток(
Stream
) - Шаблон наблюдателя
- шаблон итератора
Реактивное программирование
Реактивное программирование (Reactive Programming
), которая представляет собой событийную модель. В приведенном выше режиме асинхронного программирования мы описали два способа получения результата выполнения предыдущей задачи, один из них — тренировка активного вращения, которую мы называемProactive
Способ. Другой пассивно получает обратную связь, которую мы называемReactive
. Проще говоря, вReactive
В методе обратная связь о результате предыдущей задачи является событием, и приход этого события инициирует выполнение следующей задачи.
Идея реактивного программирования примерно такова: вы можете использовать includeClick
а такжеHover
Создавайте что угодно, включая событияData stream
(Также известный как «поток», подробности в последующих главах).Stream
Недорогое и обычное, что угодно может бытьStream
: переменные, пользовательский ввод, свойства,Cache
, структуры данных и т.д. В качестве примера представьте себеTwitter feed
Это какClick events
ТакойData stream
, вы можете прослушать его и ответить соответствующим образом.
Объедините реальность, если вы используетеVue
, должен быть в состоянии думать об этом в первый раз,Vue
Разве концепция дизайна адаптивной парадигмы программирования не является также парадигмой адаптивного программирования?В процессе написания кода нам нужно только обращать внимание на изменения данных, и нам не нужно вручную управлять изменениями представления.Такого рода изDom
Модификации слоя будут автоматически изменяться и перерисовываться по мере изменения связанных данных.
поток(Stream
)
Потоки как концепции должны быть независимыми от языка. документIO
поток,Unix
Стандартные системные потоки ввода и вывода, стандартные потоки ошибок (stdin
, stdout
, stderr
), а также упомянутый в началеTCP
поток и некоторыеWeb
базовые технологии (такие какNodejs
)правильноHTTP
Абстракцию потока запросов/ответов можно увидеть в концепции потока.
В основе программирования ответа природа потока — последовательный сбор инвентаря во временном порядке.
Для первого класса или нескольких потоков мы можем преобразовать, объединить и другие операции над ними для создания нового потока, В этом процессе поток неизменяем, то есть он будет возвращать только новый на исходной основеstream
.
Шаблон наблюдателя
Можно сказать, что среди многих шаблонов проектирования шаблон наблюдателя играет более очевидную роль во многих сценариях.
Шаблон Observer — это поведенческий шаблон проектирования, который позволяет вам определить механизм подписки, который уведомляет несколько других объектов, которые «наблюдают» за объектом, когда происходит событие.
Используйте практический пример, чтобы понять, например, если вы подписаны на услугу SMS-уведомления об изменении баланса банковской карты, то в это время, пока вы переводите деньги или покупаете товары после использования этой банковской карты для потребления, система банка даст вам push текстовое сообщение, чтобы уведомить вас, сколько денег вы тратите, что на самом деле является режимом наблюдателя.
В этом процессе наблюдаемым объектом является баланс банковской карты, а наблюдателем — пользователь.
преимущество:
- Отношения связи между целью и наблюдателем уменьшаются, и они представляют собой абстрактные отношения связи.
- Соответствует принципу инверсии зависимостей.
- Между целью и наблюдателем устанавливается спусковой механизм.
- Поддержка широковещательной связи
недостаточный:
- Зависимости между целью и наблюдателем полностью не разрешены, и есть вероятность циклических ссылок.
- При большом количестве объектов-наблюдателей выпуск уведомлений занимает много времени, что сказывается на работоспособности программы.
шаблон итератора
итератор (Iterator
) режим также называется курсорным (Sursor
) шаблон, в объектно-ориентированном программировании шаблон итератора — это шаблон проектирования, самый простой и наиболее распространенный шаблон проектирования. Шаблон итератора может отделить итеративный процесс от бизнес-логики, позволяя пользователям обращаться к каждому элементу в контейнере через определенный интерфейс, не зная базовой реализации.
const iterable = [1, 2, 3];
const iterator = iterable[Symbol.iterator]();
iterator.next(); // => { value: "1", done: false}
iterator.next(); // => { value: "2", done: false}
iterator.next(); // => { value: "3", done: false}
iterator.next(); // => { value: undefined, done: true}
Как фронтенд-разработчики, наиболее распространенное развертывание, с которым мы сталкиваемся, этоiterator
Существует множество интерфейсных структур данных:Map
,Set
,Array
, массив классов и т. д. В процессе их использования мы можем использовать один и тот же интерфейс для доступа к каждому элементу, то есть использовать шаблон итератора.
Iterator
эффект:
- Обеспечить единый и удобный интерфейс доступа к различным структурам данных;
- Позволяет расположить элементы структуры данных в определенном порядке;
- для нового синтаксиса обхода
for...of
петля реализации
Во многих статьях некоторые любят смешивать итераторы и траверсеры для концептуального анализа, на самом деле они выражают один и тот же смысл, или можно сказать (итераторы равны траверсерам).
Observable
Представляет концепцию, которая представляет собой вызываемую коллекцию будущих значений или событий. Он может использоваться несколькимиobserver
Подписка, каждое отношение подписки не зависит друг от друга и не влияет друг на друга.
Возьмите каштан:
Предположим, вы подписаны на блог или учетную запись службы, которая отправляет статьи (например, общедоступную учетную запись WeChat), а затем, пока общедоступная учетная запись обновляет новый контент, общедоступная учетная запись будет отправлять вам новую статью. учетная записьObservable
, источник данных, используемый для создания данных.
Поверьте, что прочитав приведенное выше описание, вы должны быть правыObservable
Если у вас есть определенное представление о том, что это такое, то с этим легко справиться.RxJS
как создатьObservable
.
const Rx = require('rxjs/Rx')
const myObservable = Rx.Observable.create(observer => {
observer.next('foo');
setTimeout(() => observer.next('bar'), 1000);
});
мы можем позвонитьObservable.create
метод созданияObservable
, этот метод принимает в качестве параметра функцию, эта функция вызываетсяproducer
функция для генерацииObservable
ценность . Параметры этой функцииobserver
, внутри функции, вызвавobserver.next()
для генерации последовательности значенийObservable
.
мы должны игнорировать
observer
это то, что начинается с созданияObservable
С точки зрения метода, по сути, это вызовAPI
Вещи, очень простые, такие простыеObservable
Объект создан.
Observer
Набор функций обратного вызова, которые умеют прослушиватьObservable
предоставленная стоимость.Observer
В сигнальном потоке есть роль наблюдателя (сторожевого), который отвечает за наблюдение за статусом выполнения задачи и подачу сигналов в поток.
Здесь мы просто реализуем внутреннюю структуру:
const observer = {
next: function(value) {
console.log(value);
},
error: function(error) {
console.log(error)
},
complete: function() {
console.log('complete')
}
}
существуетRxJS
середина,Observer
является необязательным. существуетnext
,error
а такжеcomplete
В случае, когда логическая часть обработки отсутствует,Observable
Все еще работающая, логика обработки для включенного определенного типа уведомления автоматически игнорируется.
Например, мы можем определить это так:
const observer = {
next: function(value) {
console.log(value);
},
error: function(error) {
console.log(error)
}
}
До сих пор нормально работает.
Так как же это вяжется с нами в реальном бою:
const myObservable = Rx.Observable.create((observer) => {
observer.next('111')
setTimeout(() => {
observer.next('777')
}, 3000)
})
myObservable.subscribe((text) => console.log(text));
используйте прямо здесьsubscribe
способ сделатьobserver
подписаться одинObservable
, мы можем посмотреть на этоsubscribe
Определение функции, чтобы увидеть, как реализовать подписку:
subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription;
Исходный код используетсяts
Написанный код представляет собой документ, который очень понятен. Здесь автор объяснит вам это. С точки зрения отсчета, слева направо:next
,error
,complete
, и является необязательным, мы можем сами выборочно передавать соответствующие обратные вызовы, что подтверждает то, что мы сказали выше.next
,error
а такжеcomplete
Логическая часть обработки отсутствует и все еще работает нормально, потому что все они являются необязательными.
Подписка и тема
Subscription
Subscription
означаетObservable
Исполнение можно почистить. Наиболее распространенным методом этого объекта являетсяunsubscribe
метод, он не требует никаких параметров и используется только для очисткиSubscription
занятые ресурсы. В то же время он также имеетadd
метод позволяет нам отменить несколько подписок.
const myObservable = Rx.Observable.create(observer => {
observer.next('foo');
setTimeout(() => observer.next('bar'), 1000);
});
const subscription = myObservable.subscribe(x => console.log(x));
// 稍后:
// 这会取消正在进行中的 Observable 执行
// Observable 执行是通过使用观察者调用 subscribe 方法启动的
subscription.unsubscribe();
Тема
Это прокси-объект, который одновременноObservable
Еще одинObserver
, он может принять обаObservable
Передаваемые данные также могут быть отправлены наobserver
передавать данные, тем временем,Subject
к внутреннемуobservers
список для многоадресной рассылки (multicast
)
Subjects
произвольноObservable
Единственный способ разделить выполнение с несколькими наблюдателями
На этот раз зоркие читатели обнаружат, что здесь возникло новое понятие — мультикаст.
- Так что же так транслируется?
- С многоадресной рассылкой есть ли еще одноадресная рассылка?
- В чем их отличие?
Далее позвольте автору дать вам лучший анализ этих двух концепций.
Одноадресная передача
обычныйObservable
Это одноадресная передача, так что же такое одноадресная?
Unicast означает, что каждый обычныйObservables
Экземпляр может быть подписан только одним наблюдателем, и новый экземпляр будет создан, когда на него подпишутся другие наблюдатели. это обычное делоObservables
При подписке разными наблюдателями будет несколько экземпляров.Независимо от того, когда наблюдатель начинает подписываться, каждый экземпляр отправляет значение соответствующему наблюдателю с самого начала.
const Rx = require('rxjs/Rx')
const source = Rx.Observable.interval(1000).take(3);
source.subscribe((value) => console.log('A ' + value))
setTimeout(() => {
source.subscribe((value) => console.log('B ' + value))
}, 1000)
// A 0
// A 1
// B 0
// A 2
// B 1
// B 2
Не паникуйте, увидев незнакомые звонки, подробный анализ будет позже, здесь
source
Вы можете понять, что каждая секунда - это отправка целого числа с шагом 0Observable
будет работать и будет отправлено только три раза (take
Фактически оператор ограничивает количество принимаемых номеров и не отправляет данные. ).
Отсюда видно, что два разных наблюдателя подписываются на один и тот же источник (source
), один для прямой подписки, а другой для подписки с задержкой в одну секунду.
Из распечатанных результатовA
Печать растущего числа с нуля каждую секунду иB
Задержка на секунду, затем начните печать с 0, который виден,A
а такжеB
Выполнение полностью раздельное, то есть для каждой подписки создается новый экземпляр.
Во многих сценариях мы можем захотетьB
Чтобы иметь возможность не принимать данные с самого начала, а принимать данные, отправляемые в данный момент в момент подписки, для этого необходимо использовать возможности многоадресной рассылки.
многоадресная рассылка
Поэтому, если вы реализуете многоадресные возможности, это для достижения функции США только получают данные в реальном времени.
Может быть, небольшой партнер выскочет в это время, непосредственно подписывайтесь на источник в посредник, а затем пересылать данные вA
а такжеB
Разве это не сработает?
const source = Rx.Observable.interval(1000).take(3);
const subject = {
observers: [],
subscribe(target) {
this.observers.push(target);
},
next: function(value) {
this.observers.forEach((next) => next(value))
}
}
source.subscribe(subject);
subject.subscribe((value) => console.log('A ' + value))
setTimeout(() => {
subject.subscribe((value) => console.log('B ' + value))
}, 1000)
// A 0
// A 1
// B 1
// A 2
// B 2
Давайте сначала проанализируем код,A
а такжеB
Нет никакой разницы между подпиской и одноадресным кодом, единственное, что меняется, это то, что объекты, на которые они подписываются,source
сталsubject
А потом посмотри на этоsubject
Что входит, здесь сделаны некоторые упрощения, убраныerror
,complete
Такая функция обработки сохраняет толькоnext
, затем содержитobservers
Массив, который содержит всех подписчиков, предоставляетsubscribe
Используется наблюдателями для подписки на него.
В использовании, пусть этот посредникsubject
Подписатьсяsource
, чтобы добиться унифицированного управления и обеспечить характер данных в реальном времени, потому что в основном дляsource
Например, есть только один подписчик.
Это в основном для удобства понимания и легкой реализации.
RxJS
серединаSubject
, где посредника можно заменить напрямуюRxJS
изSubject
экземпляр класса, эффект тот же
const source = Rx.Observable.interval(1000).take(3);
const subject = new Rx.Subject();
source.subscribe(subject);
subject.subscribe((value) => console.log('A ' + value))
setTimeout(() => {
subject.subscribe((value) => console.log('B ' + value))
}, 1000)
Кроме того, давайте сначала посмотрим, соответствует ли распечатанный результат ожидаемомуA
Результат печати не меняется,B
Число, напечатанное в первый раз, теперь начинается с 1, то есть данных, которые в настоящее время передаются, что удовлетворяет нашу потребность в получении данных в реальном времени.
В отличие от абонентов одноадресной рассылки, которым всегда необходимо получать данные с нуля, многоадресный режим обеспечивает передачу данных в реальном времени.
Помимо вышеперечисленного,RxJS
также обеспечиваетSubject
Три варианта:
BehaviorSubject
ReplaySubject
AsyncSubject
BehaviorSubject
BehaviorSubject
Это новая подписка, которая дополнительно выдает самое последнее выпущенное значение.Subject
.
]
Точно так же мы понимаем это в сочетании с реальными сценариями. Предположим, нам нужно использовать его для поддержания состояния. После его изменения мы можем отправить текущее состояние данных всем повторным подписчикам. Это как мы хотим реализовать Мы заботимся только о конечном состоянии вычисляемого свойства, но не о количестве изменений в процессе, так что же нам делать?
мы знаем обычныеSubject
Текущие данные будут отправлены только при наличии новых данных, а отправленные данные не будут отправлены после отправки, поэтому в это время мы можем ввестиBehaviorSubject
Сопровождение конечного состояния выполняется, потому что наблюдатель, который подписывается на объект, может получать самое последнее значение, отправленное объектом во время подписки, что может удовлетворить нашим вышеуказанным требованиям.
Затем объедините код для анализа этогоSubject
Сценарии применения:
const subject = new Rx.Subject();
subject.subscribe((value) => console.log('A:' + value))
subject.next(1);
// A:1
subject.next(2);
// A:2
setTimeout(() => {
subject.subscribe((value) => console.log('B:' + value)); // 1s后订阅,无法收到值
}, 1000)
Первая демонстрация заключается в использовании обычныхSubject
как подписанный объект, а затем наблюдательA
в объекте экземпляраsubject
передачаnext
Подписывается перед отправкой нового значения, а затем наблюдатель подписывается после задержки в одну секунду, поэтомуA
Прием данных нормальный, то на этот раз из-заB
Он не был подписан, когда данные были отправлены, поэтому он не получил данные.
Тогда давайте посмотрим наBehaviorSubject
Достигнутый эффект:
const subject = new Rx.BehaviorSubject(0); // 需要传入初始值
subject.subscribe((value: number) => console.log('A:' + value))
// A:0
subject.next(1);
// A:1
subject.next(2);
// A:2
setTimeout(() => {
subject.subscribe((value: number) => console.log('B:' + value))
// B:2
}, 1000)
Также из распечатанных результатов, так же, как и в обычномSubject
Разница в том, что в то время как подписка, исходный объект отправляет самое последнее измененное значение (или начальное значение, если оно не изменилось). В это время нашB
Также получил последний статус.
создание экземпляра здесь
BehaviorSubject
Вам нужно передать начальное значение.
ReplaySubject
в пониманииBehaviorSubject
понять позжеReplaySubject
это легче,ReplaySubject
Все значения будут сохранены, а затем воспроизведены для новых подписчиков, и он предоставляет входной параметр для управления количеством воспроизводимых значений (по умолчанию воспроизводить все).
]
Какой? Все еще не понимаете? Посмотрите на код:
const subject = new Rx.ReplaySubject(2);
subject.next(0);
subject.next(1);
subject.next(2);
subject.subscribe((value: number) => console.log('A:' + value))
// A:1
// A:2
subject.next(3);
// A:3
subject.next(4);
// A:4
setTimeout(() => {
subject.subscribe((value: number) => console.log('B:' + value))
// B:3
// B:4
}, 1000)
// 整体打印顺序:
// A:1
// A:2
// A:3
// A:4
// B:3
// B:4
Давайте сначала посмотрим на параметры, переданные конструктору,BehaviorSubject
а такжеReplaySubject
Вам нужно передать параметр, правильноBehaviorSubject
является начальным значением дляReplaySubject
Другими словами, сколько раз нужно воспроизвести предыдущее значение, если счетчик повторов не передан, то будут воспроизведены все переданные значения.
По результатам, если не пройти определенное количество повторов, достигаемый эффект почти такой же, как и введенный ранее эффект unicast.
Таким образом, мы можем проанализировать код, чтобы узнать, сколько раз значение, отправленное исходным объектом, может быть получено наблюдателями в момент подписки.
AsyncSubject
AsyncSubject
только тогда, когдаObservable
По завершении выполнения (выполнитьcomplete()
), он отправит наблюдателю последнее значение выполнения, если оно завершится с исключением,AsyncSubject
не будет публиковать никаких данных, но будетObserver
Передайте уведомление об исключении.
]
AsyncSubject
Обычно он используется меньше, а первые три используются чаще.
const subject = new Rx.AsyncSubject();
subject.next(1);
subject.subscribe(res => {
console.log('A:' + res);
});
subject.next(2);
subject.subscribe(res => {
console.log('B:' + res);
});
subject.next(3);
subject.subscribe(res => {
console.log('C:' + res);
});
subject.complete();
subject.next(4);
// 整体打印结果:
// A:3
// B:3
// C:3
Из результатов печати на самом деле хорошо понятно, то есть для всех наблюдателей исходный объект будет вызываться только после отправки всех данных.complete
Только после метода наблюдателям будут возвращены последние данные.
Это похоже на то, что часто можно увидеть в романах: когда вы хотите использовать навыки, вы должны сначала сыграть набор начальных ходов, а затем вы отпустите свой последний ход после того, как закончите.
Холодные наблюдаемые против горячих наблюдаемых
Cold Observables
Cold Observables
только поobservers
Когда вы подпишетесь, он начнет генерировать значения. Это одноадресная рассылка. Количество подписок равно количеству экземпляров подписки. Каждая подписка начинает получать значение из первого сгенерированного значения, поэтому значение, полученное каждой подпиской, одинаково.
Если вы хотите обратиться к
Cold Observables
Для получения соответствующего кода просто посмотрите на предыдущий пример одноадресной рассылки.
Поскольку одноадресная рассылка описывает возможность, всякий раз, когда наблюдатели начинают подписываться, исходный объект будет отправлять все числа наблюдателю, начиная с начального значения.
Hot Observables
Hot Observables
Производит значение независимо от того, подписано оно или нет. Это многоадресная рассылка, несколько подписок совместно используют один и тот же экземпляр, и значение получено с начала подписки. Значение, полученное каждой подпиской, отличается в зависимости от того, когда они начали подписываться.
Здесь есть несколько сценариев, мы можем проанализировать их один за другим для простоты понимания:
"обогрев"
Во-первых, вы можете игнорировать незнакомые функции, которые появляются в коде, что будет подробно рассмотрено позже.
const source = Rx.Observable.of(1, 2).publish();
source.connect();
source.subscribe((value) => console.log('A:' + value));
setTimeout(() => {
source.subscribe((value) => console.log('B:' + value));
}, 1000);
Здесь первое использованиеRx
Операторof
создалObservable
, за которым следуетpublish
функция, вызываемая после созданияconnect
функция начала передачи данных.
Результат выполнения конечного кода - данные не выводятся.На самом деле проще понять причину, проанализировав причину.Поскольку нет подписки при включении передачи данных, а этоHot Observables
, ему все равно, подписаны вы на него или нет, он будет отправлять данные сразу после включения, так чтоA
а такжеB
Данные не получены.
Конечно, если поставить
connect
Метод помещается в конец, затем конечный результатA
получено,B
до сих пор не могу понять, потому чтоA
подписался до начала отправки данных, иB
Еще одна секунда.
более интуитивная сцена
Как описано выше в многоадресной рассылке, на самом деле то, что мы хотим видеть больше, — это возможностьA
а такжеB
Два наблюдателя могут как получать данные, так и затем наблюдать разницу в данных, что будет легче понять.
Вот прямое изменение источника выбросов:
const source = Rx.Observable.interval(1000).take(3).publish();
source.subscribe((value: number) => console.log('A:' + value));
setTimeout(() => {
source.subscribe((value: number) => console.log('B:' + value));
}, 3000);
source.connect();
// A:0
// A:1
// A:2
// B:2
Здесь мы используемinterval
Сотрудничатьtake
Второй оператор передает инкрементное число, до трех, то результат печати на этот раз даже более понятны,A
Три номера принимаются нормально,B
Подписка через три секунды, поэтому получена только последняя цифра 2, что и является мультикастом, описанным выше.
Сравните два
-
Cold Observables
: будет легче понять, если мы дадим каштан: например, если мы пойдем на станцию B, чтобы посмотреть шоу и обновить новое шоу, независимо от того, когда мы его смотрим, мы можем посмотреть весь эпизод с самого начала, и это не имеет никакого отношения к тому, смотрят это другие люди или нет., не мешайте друг другу. -
Hot Observables
: Это как когда мы идем на станцию Б смотреть прямую трансляцию.После начала прямой трансляции она начинает играть сразу вне зависимости от того есть подписчики или нет.То есть если вы не подписались на нее на момент начало, то через некоторое время посмотришь, да содержание предыдущего прямого эфира я не знаю.
Разбор оператора, который появляется в приведенном выше коде
при созданииHot Observables
когда мы использовалиpublish
а такжеconnect
Комбинация функций фактически вызываетpublish
Результат, возвращаемый после того, как оператор являетсяConnectableObservable
, а затем предоставляется на этом объектеconnect
методы позволяют нам контролировать, когда данные отправляются.
-
publish
: Этот оператор преобразует нормальныйObservable
(Cold Observables
) вConnectableObservable
. -
ConnectableObservable
:ConnectableObservable
это многоадресный ресурсObservable
, может использоваться несколькимиobservers
общая подписка, этоHot Observables
.ConnectableObservable
является подписчиком и истинным источникомObservables
(в примере вышеinterval
, который отправляет значение каждую секунду, которое является источникомObservables
) посредник,ConnectableObservable
из источникаObservables
Значение принимается и затем пересылается подписчику. -
connect()
:ConnectableObservable
не отправляет активно значения, он имеетconnect
метод, позвонивconnect
метод, который позволяет делитьсяConnectableObservable
отправить значение. когда мы звонимConnectableObservable.prototype.connect
Метод, независимо от того, подписан он или нет, отправит значение. Подписчики используют один и тот же экземпляр, и ценность, которую получают подписчики, зависит от того, когда они начали подписываться.
На самом деле, этот метод ручного управления довольно хлопотный, есть ли более удобный метод работы, например, контролировать подписчиков на подписку перед началом отправки данных, а после отмены всех подписчиков прекратить отправку данных? На самом деле есть, посмотрим на счетчик ссылок(refCount
):
подсчет ссылок
В основном используется здесьpublish
комбинироватьrefCount
Для достижения эффекта «автоматической блокировки».
const source = Rx.Observable.interval(1000).take(3).publish().refCount();
setTimeout(() => {
source.subscribe(data => { console.log("A:" + data) });
setTimeout(() => {
source.subscribe(data => { console.log("B:" + data) });
}, 1000);
}, 2000);
// A:0
// A:1
// B:1
// A:2
// B:2
Когда мы смотрим на суть через результаты, мы можем легко обнаружить, что только тогда, когдаA
Начинайте отправлять данные только после подписки (A
Полученные данные начинаются с 0), и когдаB
При подписке можно получить только текущие отправленные данные, но нельзя получить предыдущие данные.
Мало того, этот «автоблок» перестает отправлять данные, когда все подписчики отписываются.
Планировщики
Используется для управления параллелизмом и представляет собой централизованный планировщик, который позволяет нам координировать, когда происходят вычисления, например.setTimeout
илиrequestAnimationFrame
или другие.
- Планировщик — это структура данных. Он знает, как хранить и упорядочивать задачи на основе приоритета или других критериев.
- Планировщик — это контекст выполнения. Он указывает, когда и где выполнять задачу (например, немедленно или другой механизм функции обратного вызова (такой как
setTimeout
илиprocess.nextTick
) или кадры анимации). - Планировщик имеет (виртуальные) часы. Функция планировщика передает свое
getter
методnow()
Дает понятие «время». Задачи, запланированные в определенном планировщике, будут строго соответствовать времени, представленному этими часами.
Узнав об этом, я считаю, что все были более или менее правы.RxJS
У меня есть определенное понимание.Не знаю, нашли ли вы вопрос.Приведенные выше примеры кода имеют и синхронный, и асинхронный, но автор не показывает контроль их выполнения.Какой у них механизм выполнения?
На самом деле, их внутреннее планирование зависит отSchedulers
Чтобы контролировать время передачи данных, многие операторы устанавливают различныеScheduler
, поэтому нам не нужно выполнять специальную обработку, они могут нормально работать синхронно или асинхронно.
const source = Rx.Observable.create(function (observer: any) {
observer.next(1);
observer.next(2);
observer.next(3);
observer.complete();
});
console.log('订阅前');
source.observeOn(Rx.Scheduler.async) // 设为 async
.subscribe({
next: (value) => { console.log(value); },
error: (err) => { console.log('Error: ' + err); },
complete: () => { console.log('complete'); }
});
console.log('订阅后');
// 订阅前
// 订阅后
// 1
// 2
// 3
// complete
Судя по результатам печати, время отправки данных действительно изменилось с синхронного на асинхронное, и если метод планирования не изменен, печать "после подписки" должна выполняться после отправки данных.
После прочтения примера давайте изучим, какие виды планирования может выполнять этот планировщик:
queue
asap
async
animationFrame
queue
ставить каждую следующую задачу в очередь вместо немедленного выполнения
queue
Планировщик использования задержки, его поведениеasync
Планировщик тот же.
При использовании без задержки он планирует данную задачу синхронно - как только задача запланирована. Однако при рекурсивном вызове (т.е. внутри запланированной задачи) другая задача будет запланирована с использованием планировщика очереди, вместо немедленного выполнения задача будет помещена в очередь и будет ожидать завершения текущей задачи.
Это означает, что при использованииqueue
Когда планировщик выполняет задачу, вы можете быть уверены, что она завершится до того, как начнутся любые другие задачи, запланированные этим планировщиком.
Эта синхронизация может не совпадать с той синхронизацией, которую мы обычно понимаем, и автор некоторое время был в замешательстве.
Давайте используем официальный пример, чтобы объяснить, как понимается этот метод планирования:
import { queueScheduler } from 'rxjs';
queueScheduler.schedule(() => {
queueScheduler.schedule(() => console.log('second'));
console.log('first');
});
Нам не нужно обращать внимание на незнакомые вызовы функций, здесь мы сосредоточимся на отличии этого метода планирования от обычного синхронного планирования.
Сначала мы звонимqueueScheduler
изschedule
Метод начинает выполняться, а затем снова вызывается функция таким же образом (её тоже можно изменить на рекурсию, но может лучше понять это на этом примере), и передаем функцию, выводимsecond
.
Затем продолжайте смотреть на следующее утверждение, обычноеconsole.log('first')
, а затем посмотрим на результат печати:
// first
// second
Разве это не немного волшебно, если вы не понимаете, почему, вы можете оглянуться назад и посмотреть впередqueue
Как обрабатывать рекурсивное выполнение. То есть, если он вызывается рекурсивно, он будет поддерживать внутреннюю очередь, а затем ждать, пока задачи, добавленные в очередь первыми, будут выполнены первыми (т.console.log('first')
будет выполняться после выполненияconsole.log('second')
,потому чтоconsole.log('second')
Эта задача будет добавлена в очередь позже).
asap
Внутренне основанныйPromise
выполнить(Node
конечное применениеprocess.nextTick
), он будет использовать самый быстрый асинхронный механизм передачи, если не поддерживаетсяPromise
илиprocess.nextTick
илиWeb Worker
изMessageChannel
также может позвонитьsetTimeout
способ запланировать.
async
а такжеasap
Способ очень похож, но внутреннее применениеsetInterval
Планирование, в основном используется для операторов, основанных на времени.
animationFrame
Судя по названию, я считаю, что кое-что уже может знать каждый.Внутренняя основа основана наrequestAnimationFrame
для реализации планирования, поэтому время выполнения будет таким же, какwindow.requestAnimationFrame
Последовательный, подходит для сцен, требующих частого рендеринга или управления анимацией.
Operators
Концепция оператора
Чистые функции в стиле функционального программирования (pure function
), используя что-то вродеmap
,filter
,concat
,flatMap
Подождите, пока такие операторы будут работать с коллекциями. Из-за его чистого определения функции мы можем знать, что вызов любого оператора не изменит существующийObservable
экземпляр, но вернет новый на основе исходногоObservable
.
несмотря на то что
RxJS
ОсноваObservable
, но наиболее полезными являются его операторы. Операторы — это основные единицы кода, которые позволяют легко составлять сложный асинхронный код в декларативной манере.
реализовать оператор
Предположим, мы не используемRxJS
Предоставленный оператор фильтра, так что же делать, если вы хотите реализовать его самостоятельно?
function filter(source, callback) {
return Rx.Observable.create(((observer) => {
source.subscribe(
(v) => callback(v) && observer.next(v),
(err) => observer.error(err),
(complete) => observer.complete(complete)
);
}))
}
const source = Rx.Observable.interval(1000).take(3);
filter(source, (value) => value < 2).subscribe((value) => console.log(value));
// 0
// 1
Это достигается простымfilter
Оператор, это очень лаконично?На самом деле основной метод, как было сказано выше, основан на входящемObservable
, возвращает новыйObservable
.
Сначала код создаетObservable
, затем используйте нового наблюдателя, чтобы подписаться на входящий источник, и вызовите функцию обратного вызова, чтобы определить, нужно ли продолжать отправлять значение, если оноfalse
, а затем пропустите его напрямую.В соответствии с функцией источника и фильтра, которую мы передали, исходный объект в конечном итоге отправит три числа 0, 1 и 2, а результат печати — 0, 1 и 2 отфильтрованы.
Конечно, мы также можем разместить его вRx.Observable.prototype
чтобы мы могли использоватьthis
Способ получения источника:
Rx.Observable.prototype.filter = function (callback) {
return Rx.Observable.create(((observer) => {
this.subscribe(
(v) => callback(v) && observer.next(v),
(err) => observer.error(err),
(complete) => observer.complete(complete)
);
}))
}
Rx.Observable.interval(1000).take(3).filter((value) => value < 2).subscribe((value) => console.log(value));
// 0
// 1
Разве это не было бы более кратким, как мы использовали нативные массивыfilter
Так же.
Если говорить о разнице между этими двумя методами, то ее на самом деле легче понять.prototype
, объект, который может быть создан, можно вызвать напрямую, а другой — определить новую функцию, которую можно использовать для экспорта в вызывающую программу (на самом деле, ее также можно напрямую смонтировать вObservable
на статическом свойстве).
Увидев это, оценивается, что некоторые читатели догадались, что автор объяснит дальше.
оператор экземпляра - статический оператор
- Оператор экземпляра: Обычно это оператор, который может быть вызван непосредственно созданным объектом. Обычно мы используем больше операторов экземпляров, таких как
filter
,map
,concat
и т.п. Более удачное использование операторов экземпляровthis
, опуская параметр и сохраняя связанный вызов. - Статический оператор:
Observable
Являетсяclass
класс, мы можем напрямую смонтировать оператор в его статическое свойство, преимущество в том, что его можно вызывать без создания экземпляра, недостаток в том, что его больше нельзя использоватьthis
Способ вызова целевого объекта, но вам нужно передать целевой объект.
Если добавление экземпляра свойства уже было примером, я не буду вдаваться здесь в подробности.
вышесказанноеfilter
Например, измените его и смонтируйте на статическом свойстве:
Rx.Observable.filter = (source, callback) => {
return Rx.Observable.create(((observer) => {
source.subscribe(
(v) => callback(v) && observer.next(v),
(err) => observer.error(err),
(complete) => observer.complete(complete)
);
}))
}
Операторы создания
Для обработки или использования любых данных первое, на чем мы сосредоточимся, - это то, откуда она пришла, как он был сгенерирован, и как мы можем его получить.
create
определение:
public static create(onSubscription: function(observer: Observer): TeardownLogic): Observable
После крещения предыдущего кода, я считаю, что всем не чужд этот оператор.
create
БудуonSubscription
функцию в фактическуюObservable
. всякий раз, когда кто-то подписывается наObservable
когда,onSubscription
Функция получитObserver
Экземпляр выполняется как единственный параметр.onSubscription
должен вызывать объект наблюдателяnext
,error
а такжеcomplete
метод.
Описание официального документа на самом деле очень понятное, что эквивалентно созданию оператора, пока кто-то подписывается на него.Observable
, который передает ряд значений, вызывая методы у самого подписчика.
Изображение выше не имеет прямого отношения к демонстрационному коду.
const source = Rx.Observable.create(((observer: any) => {
observer.next(1);
observer.next(2);
setTimeout(() => {
observer.next(3);
}, 1000)
}))
// 方式一
source.subscribe(
{
next(val) {
console.log('A:' + val);
}
}
);
// 方式二
source.subscribe((val) => console.log('B:' + val));
// A:1
// A:2
// B:1
// B:2
//- 1s后:
// A:3
// B:3
Естественно, о результате печати говорить не приходится.A
а такжеB
Будет печатать 1, 2 отдельно и печатать 3 через 1 с.
Здесь мы можем заметить, что наш вызовsubscribe
Эти два метода можно использовать, когдаnext
,error
,complete
Три метода (все необязательные), или способ прямой передачи в функцию, параметры соответственно до и послеnext
,error
,complete
.
empty
определение:
public static empty(scheduler: Scheduler): Observable
Как следует из названия, этот оператор создает оператор, который не выдает никаких данных и напрямую отправляет уведомление о завершении.
Некоторые читатели могут спросить здесь, какая польза от этой штуки.
На самом деле это не так, когда он сотрудничает с некоторыми операторами, его роль нельзя недооценивать, например,mergeMap
, будет объяснено позже, те, кому не терпится, могут сразу перейти кmergeMap
.
from
определение:
public static from(ish: ObservableInput<T>, scheduler: Scheduler): Observable<T>
из массива, массивоподобного объекта,Promise
, объект или класс итератораObservable
объект создаетObservable
.
Этот метод немного похожjs
серединаArray.from
метод (который может создать новый массив из массивоподобного или итерируемого объекта), но только вRxJS
превращается вObservable
для использования пользователями.
const source = Rx.Observable.from([10, 20, 30]);
source.subscribe(v => console.log(v));
// 10
// 20
// 30
Судя по коду примера, на самом деле это относительно простое использование.Если вы хотите использовать некоторые данные (например, массивы или массивы, подобные массивам) для существующих проектовRxJS
управлять, тоfrom
Операция будет хорошим выбором.
fromEvent
определение:
public static fromEvent(target: EventTargetLike, eventName: string, options: EventListenerOptions, selector: SelectorMethodSignature<T>): Observable<T>
СоздаватьObservable
,ДолженObservable
Испускает событие указанного типа из данного объекта события. доступно в среде браузераDom
событие илиNode
в окружающей средеEventEmitter
Событие и т. д.
Предположим, у нас есть такое требование, слушайте события нажатия кнопки и распечатывайте их:
const click = Rx.Observable.fromEvent(document.getElementById('btn'), 'click');
click.subscribe(x => console.log(x));
Сравните наше использованиеaddEventListener
Способ мониторинга заключается в том, что этот способ письма более беглый.
fromPromise
определение:
public static fromPromise(promise: PromiseLike<T>, scheduler: Scheduler): Observable<T>
С точки зрения названия это уже очевидно, т.Promise
Перевести вObservable
, так что мы можем писать код без написания.then
,.catch
цепные вызовы, как это.
еслиPromise resolves
значение, выводObservable
Выдайте это значение, и все готово. еслиPromise
одеялоrejected
, выходObservable
Будет выдана соответствующая ошибка.
const source = Rx.Observable.fromPromise(fetch('http://localhost:3000'));
source.subscribe(x => console.log(x), e => console.error(e));
Здесь для демонстрации эффекта настраивается локальный сервис для тестирования, а для самотестирования можно использовать другие.
Таким образом, мы можем легко получить возвращаемое значение запроса.
interval
определение:
public static interval(period: number, scheduler: Scheduler): Observable
созданный с помощью этого оператораObservable
Может выдавать последовательные числа в течение заданного времени, на самом деле просто используйте это вместе с намиsetInterval
Этот шаблон примерно одинаково. Этот оператор может быть использован для достижения наших потребностей, когда нам нужно получить непрерывное число, или когда нам нужно регулярно выполнять некоторые операции.
const source = Rx.Observable.interval(1000);
source.subscribe(v => console.log(v));
Значение по умолчанию начинается с 0. Время, установленное здесь, равно 1 с. Он будет продолжать отправлять данные с указанным интервалом. Как правило, мы можем комбинироватьtake
оператора для ограничения объема передаваемых данных.
of
определение:
public static of(values: ...T, scheduler: Scheduler): Observable<T>
а такжеfrom
Способность не слишком отличается, но при ее использовании вызывается путем передачи параметров один за другим, что чем-то похоже наjs
серединаconcat
метод. также вернетObservable
, который, в свою очередь, объединяет параметры, которые вы передаете, и синхронно передает данные.
const source = Rx.Observable.of(1, 2, 3);
source.subscribe(v => console.log(v));
// 1
// 2
// 3
Выведите 1, 2, 3 последовательно.
repeat
определение:
public repeat(count: number): Observable
Дублирующийся источник данныхn
Второсортный,n
для параметра числового типа, который вы передаете.
const source = Rx.Observable.of(1, 2, 3).repeat(3);
source.subscribe(v => console.log(v));
Здесь сof
Оператор, результат печати состоит в том, чтобы распечатать 1, 2, 3, 1, 2, 3, 1, 2, 3 одновременно и преобразовать 1, 2 и 3, которые были первоначально напечатаны только один раз в три раза.
range
определение:
public static range(start: number, count: number, scheduler: Scheduler): Observable
СоздаватьObservable
, который выдает последовательность чисел в указанном диапазоне.
научился
Python
У маленьких друзей дерева возникает ощущение дежавю.
const source = Rx.Observable.range(1, 4);
source.subscribe(v => console.log(v));
Распечатать результаты: 1, 2, 3, 4.
Это кажется простым?
оператор преобразования
Итак, что такое оператор преобразования?Как мы все знаем, в нашей повседневной деятельности нам всегда приходится иметь дело с разнообразными данными.Во многих случаях мы не используем непосредственно передаваемые данные, а делаем определенное преобразование, придающее им форму это лучше соответствует нашим потребностям.Именно здесь в игру вступает оператор преобразования.
buffer
определение:
public buffer(closingNotifier: Observable<any>): Observable<T[]>
собирать прошлые значения в массив и только тогда, когда другиеObservable
Этот массив создается только при выдаче уведомления. Это эквивалентно наличию буфера, сбору данных, ожиданию прихода сигнала и его освобождению.
;
Смена оператора немного похожа на большую плотину: иногда мы выбираем запас воды, и в определенное время лидер приказывает открыть плотину и выпустить воду.
Возьмите каштан:
Предположим, у нас есть такое требование.У нас есть интерфейс, который специально используется для получения определенных данных, но этот интерфейс возвращает только одни данные за раз, что нас очень огорчает, потому что продукт хочет, чтобы количество данных достигло определенного значения. а потом управляет операцией., то есть он нажимает кнопку и потом рендерит данные.Что нам делать?
Это когда нам нужноbuffer
В дело вступает оператор:
const btn = document.createElement('button');
btn.innerText = '你点我啊!'
document.body.appendChild(btn);
const click = Rx.Observable.fromEvent(btn, 'click');
const interval = Rx.Observable.interval(1000);
const source = interval.buffer(click);
source.subscribe(x => console.log(x));
Здесь мы непосредственно используем
interval
Продемонстрировать интерфейс для получения данных, а затем сотрудничатьbuffer
Функциональная реализация.
Здесь мы будем ждать четырех секунд, а затем щелкните кнопки, распечатайте значения:[0, 1, 2, 3]
, затем подождите еще 8 секунд и нажмите кнопку:[4, 5, 6, 7, 8, 9, 10, 11]
.
Из этого явления нетрудно увидеть, что мы реализовали отправку данных с помощью кнопок. В то же время мы можем обнаружить еще одно явление, отправленные данные будут очищаться прямо в буфере, а затем снова будут собираться новые данные.
Это на самом деле нетрудно понять.Давайте возьмем в качестве примера плотину.После того, как мы открываем плотину, чтобы выпускать воду в течение определенного периода времени, а затем закрываем ее, чтобы продолжать хранить воду, вода, которую я выпускаю во второй раз, я открываю. плотина, естественно, моя недавно сохраненная вода.
concatMap
определение:
public concatMap(project: function(value: T, ?index: number): ObservableInput, resultSelector: function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any): Observable
Этот оператор еще немного интересен, давайте взглянем на описание на официальном сайте:
Приведите исходное значение как слияние к выходу
Observable
изObservable
, подождите, пока предыдущий завершится последовательно, прежде чем объединять следующийObservable
.
Не знаю, чувствуете ли вы, читатели, "легкое" непонимание, но я легко это понимаю, если приведу небольшой пример:
Предположим, вы столкнулись с такой сценой, вы и ваша девушка вместе делаете покупки в закусочной, но у девушки есть серьезная проблема.Она всегда любит купить кусочек в этом магазине, затем позволить вам съесть остальное, а затем купить немного в в другом магазине. Откусите один кусочек, а затем дайте себе съесть остальное, и вам требуется время, чтобы поесть каждый раз. Как правило, девушка, которая расстроена своим парнем, будет ждать, пока вы закончите есть, прежде чем купить еще один. В этом случае, вы все равно можете отдохнуть после того, как закончите есть; в другом случае вашей девушке все равно, закончили вы есть или нет, она продолжает покупать, покупать и покупать, а потом вы едите все больше и больше, и вы не можете есть так быстро, как покупает ваша девушка, то в это время вы будете нести все больший и больший вес, и, наконец, вы не сможете выдержать психический взрыв.
Вышеуказанные сценарии включаютconcatMap
Несколько основных моментов и моментов, на которые следует обратить внимание:
- Исходное значение отправляет данные, затем вы передаете внутренний
Observable
Он начнет работать или отправлять данные, а абонент может получать данные, то есть внутреннийObservable
Это эквивалентно тому, чтобы всегда ждать, пока исходный объект отправит данные перед новым циклом работы, и ждать завершения текущего раунда работы, прежде чем переходить к следующему раунду. - Если текущий раунд работы не был завершен и данные, отправленные исходным объектом, получены, они будут сохранены в очереди, а затем, после завершения текущего раунда, будет проверено, есть ли еще в очереди , и если это так, следующий раунд будет запущен немедленно.
- Если внутри
Observable
Рабочее время больше, чем время интервала данных, отправляемых исходным объектом, что приводит к тому, что очередь кэша становится все больше и больше, и, наконец, вызывает проблемы с производительностью.
На самом деле распространено мнение, что на фабричной сборочной линии один отвечает за отправку материалов, а другой отвечает за производство продукции.Observable
, продукция на этом заводе будет только готовой продукцией, то есть готовой продукцией, поэтому подписчики могут получить ее только после того, как человек, изготовивший продукт, закончит ее.
Если материал высвобождается быстрее, чем производитель успевает изготовить продукт, происходит накопление материала, и со временем его будет накапливаться все больше и больше, и фабрика не сможет его уместить.
С помощью понимания кода:
const source = Rx.Observable.interval(3000);
const result = source.concatMap(val => Rx.Observable.interval(1000).take(2));
result.subscribe(x => console.log(x));
Сначала проанализируем структуру кода, мы сначала создадим исходный объект, который отправляет данные каждые три секунды, а затем вызовем метод экземпляраconcatMap
, и передать возврат методуObservable
Функция объекта, и, наконец, пройтиconcatMap
преобразованныйObservable
объект и подписаться на него.
Результат операции: сначала программа работает, на третью секундуsource
отправит первые данные, а затем мы передаем во внутреннююObservable
, начните работать, отправьте два увеличенных числа через две секунды, а затем функция подписки распечатает эти два числа шаг за шагом, ожидая одну секунду, что является 6-й секундой работы программы,source
Отправьте второй номер, на этот раз повторите описанный выше процесс.
map
определение:
public map(project: function(value: T, index: number): R, thisArg: any): Observable<R>
Если вы говорите, что используетеjs
в массивеmap
Если есть много методов, вам может не понадобиться читать их здесь, и использование точно такое же.
Вам нужно только передать функцию, тогда первый параметр функции - это все данные источника данных, а второй параметр - значение индекса данных, вам нужно только вернуть возвращаемое значение после вычисления или другой операции. as Значение, фактически полученное подписчиком.
const source = Rx.Observable.interval(1000).take(3);
const result = source.map(x => x * 2);
result.subscribe(x => console.log(x));
take
Фактически оператор ограничивает количество принимаемых номеров и не отправляет данные.
Это используется для демонстрации того, что значение каждого источника данных умножается на 2 и отправляется подписчику, поэтому напечатанные значения: 0, 2, 4.
mapTo
определение:
public mapTo(value: any): Observable
Игнорировать данные, отправленные источником данных, и отправлять только указанное значение (параметр).
Это похоже на человека, которого вы ненавидите, просящего вас помочь распространить информацию, он сказал много признаний, а затем попросил вас передать это определенной девушке, вы не хотели помогать ему, потому что ненавидели его, поэтому вы сказали девушка, что ты мне нравишься, и, наконец, Вы живете счастливо вместе.
const source = Rx.Observable.interval(1000).take(3);
const result = source.mapTo(666);
result.subscribe(x => console.log(x));
Как и в этом коде, источник данных отправляет 0, 1, 2, а подписчик фактически получает три 666.
mergeMap
определение:
public mergeMap(project: function(value: T, ?index: number): ObservableInput, resultSelector: function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any, concurrent: number): Observable
Это определение выглядит немного пугающе, но не будем паниковать, нам просто нужно понять его использование в большинстве случаев.
Ты помнишь здесь
empty
Как было сказано во введении операторов, автор оставил дыру и не восполнил ее, т.е.mergeMap
а такжеempty
Как это работает вместе? Заполните отверстие здесь.
const source = Rx.Observable.interval(1000).take(3);
const result = source.mergeMap(x => x % 2 === 0 ? Rx.Observable.of(x) : Rx.Observable.empty());
result.subscribe(x => console.log(x));
Источник ввода — это источник данных, который отправляет три числа 0, 1 и 2. Мы вызываемmergeMap
оператора, и передать функцию, функция которой состоит в том, чтобы отправить его подписчику, если текущее значение, отправленное источником ввода, является четным числом, в противном случае он его не отправит.
здесьmergeMap
В основном сделана возможность интеграции, мы можем комбинировать ее сmap
В сравнении можно найтиmap
Возвращаемое значение должно быть числовое значение, иmergeMap
Возвращаемое значение должно бытьObservable
, то есть мы можем вернуть произвольные преобразования или другие возможностиObservable
.
pluck
определение:
public pluck(properties: ...string): Observable
Используется для выбора указанного значения свойства для каждого объекта данных.
Например, данные, отправленные источником данных, являются объектом, и объект имеетname
собственность, и подписчик указывает, что знает об этомname
атрибут, то вы можете использовать этот оператор для извлечения значения атрибута для пользователя.
const source = Rx.Observable.of({name: '张三'}, {name: '李四'});
const result = source.pluck('name');
result.subscribe(x => console.log(x));
// 张三
// 李四
Нет сомнения, что этот оператор предназначен для извлечения атрибутов, что эквивалентно использованиюmap
оператор для обработки извлеченногоname
вернуться к подписчику.
scan
определение:
public scan(accumulator: function(acc: R, value: T, index: number): R, seed: T | R): Observable<R>
Оператор аккумулятора, который можно использовать для управления состоянием, имеет множество применений.
С точки зрения использования, мы можем обратиться к
js
в массивеreduce
функция.
Допустим, у нас сейчас есть требование, мы хотим аккумулировать данные, отправленные источником данных, и вернуть их подписчику, как нам это сделать?
const source = Rx.Observable.interval(1000).take(4);
const result = source.scan((acc, cur) => acc + cur, 0);
result.subscribe(x => console.log(x));
С точки зрения кода источник данных отправляет четыре значения: 0, 1, 2, 3, причем значение, получаемое абонентом каждый раз, будет суммой ранее полученного числа и текущего числа, то есть: 0, 1, 3, 6.
Затем посмотрите на использование, мы даемscan
Первый аргумент оператора передается функции, которая принимает два значения:acc
(результат предыдущего накопления или начальное значение),cur
(текущее значение), второй параметр — начальное значение расчета.
switchMap
определение:
public switchMap(project: function(value: T, ?index: number): ObservableInput, resultSelector: function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any): Observable
На самом деле, это
switch
оператор иmap
комбинация операторов,switch
Операторы рассматриваются в разделе «Объединение операторов».
Основная роль в первую очередь будет принадлежать множествуObservable
Слияние и возможность прерывания, то есть слиянияObservable
, определенныйObservable
Сначала начать отправку данных, в это время абонент может нормально получать свои данные, но в это время другойObservable
Тоже начал отправлять данные, потом первыйObservable
Отправка данных прерывается, и отправляются только данные, отправленные опоздавшим.
Говоря простым языком, когда кто-то говорит, вы вдруг начинаете громко говорить, и вас перебивают, в это время все только и слышат вас.
const btn = document.createElement('button');
btn.innerText = '我要发言!'
document.body.appendChild(btn);
const source = Rx.Observable.fromEvent(btn, 'click');
const result = source.switchMap(x => Rx.Observable.interval(1000).take(3));
result.subscribe(x => console.log(x));
Функция, реализованная кодом, заключается в том, что когда ученик нажимает на кнопку, начинается отправка числа с 0. В это время, если ученик 1 не закончил отправку данных, а ученик 2 нажимает еще раз, данные Ученик 1 больше не будет отправлен. Начните отправлять второго одноклассника.
Предположим, что после одной точки второй студент нажимает кнопку во вторую секунду, и будет напечатан результат: 0, 1, 0, 1, 2. Здесь, начиная со второго 0, это данные, отправленные вторым ученик.
другие операторы преобразования
Портал официального сайта:оператор преобразования
bufferCount
bufferTime
bufferToggle
bufferWhen
concatMapTo
exhaustMap
expand
groupBy
mergeMapTo
mergeScan
pairwise
partition
switchMapTo
window
windowCount
windowTime
windowToggle
windowWhen
оператор фильтра
debounceTime
определение:
public debounceTime(dueTime: number, scheduler: Scheduler): Observable
может быть, для определенногоjs
Небольшие партнеры с опытом разработки должны знатьdebounce
Функция защиты от сотрясений, тогда некоторые друзья спросят в это время, ее не будет сdebounce
Примерно так же? Да, его функция такая же, какdebounce
Функция защиты от сотрясений аналогична, но все же есть небольшая разница.
Только по истечении определенного периода времени, когда другое значение источника не было передано,Observable
выдает значение в .
То есть предположим, что источник данных отправляет число каждую секунду, и мы используемdebounceTime
оператора и установите время задержки, затем после того, как источник данных отправит новые данные, если источник данных отправит другие новые данные в течение времени задержки, новые данные будут сначала кэшированы и не будут отправлены, подождите После отправки данных и дожидаясь истечения времени задержки, оно будет отправлено абоненту.Мало того, когда время задержки не истекло и в буфере есть значение, и в это время получено новое значение, то буфер be Он отбросит старые данные, поместит их в новые, а затем подождет, пока не наступит время задержки, прежде чем отправлять их.
const source = Rx.Observable.interval(1000).take(3);
const result = source.debounceTime(2000);
result.subscribe(x => console.log(x));
С точки зрения кода мы могли бы также догадаться, каков будет окончательный напечатанный результат?
Сначала мы создаем источник данных, который отправляет число каждую секунду и только три раза, затем используемdebounceTime
После обработки и установки времени задержки на 2 секунды, в это время мы наблюдаем за напечатанными данными и обнаруживаем, что в первые три секунды после запуска программы печать данных не производится.Через пять секунд печатается 2, а тогда больше нет печати.теперь,почему так?
Ответ заключается в том, что источник данных каждую секунду будет посылать последовательно три числа 0, 1 и 2. Поскольку мы устанавливаем время задержки равным 2 секундам, то есть мы не можем видеть данные, пока данные не будут Поскольку частота отправки отправляющего источника составляет 1 секунду, время задержки составляет 2 секунды, то есть, если отправка не завершена, невозможно заставить отправляющий источник ждать две секунды перед отправкой новых данных. будет печататься, поэтому сколько бы номеров мы не отправляли из источника данных, в итоге подписчик получает только последний номер.
throttleTime
определение:
public throttleTime(duration: number, scheduler: Scheduler): Observable<T>
Представлено, как анти-встряска может забыть о дросселировании своего старого партнера?
Основная способность этого оператора также согласуется с известной нам функцией троттлинга, то есть он будет контролировать только одни данные, которые должны быть отправлены в течение определенного периода времени, а лишние будут отбрасываться напрямую. Единственное несоответствие с оператором debounce заключается в том, что он не блокирует первое значение.
const source = Rx.Observable.interval(1000).take(6);
const result = source.throttleTime(2000);
result.subscribe(x => console.log(x));
// 0
// 3
Результат печати показан выше. На самом деле эффект легко объяснить. Источник данных создается в коде для отправки номера, который увеличивается с 0 каждую секунду. Всего отправляется 6 чисел, то есть 0-5 и использоватьthrottleTime
Установите две секунды, подписчик не будет заблокирован при получении первого значения, но не получит значение в течение двух секунд после получения одного, то есть он может получить только 3 на четвертой секунде.
distinct
определение:
public distinct(keySelector: function, flushes: Observable): Observable
Этот оператор также очень прост для понимания, его можно охарактеризовать одним предложением При использовании этого оператора данные, полученные подписчиком, не будут дублироваться, то есть он используется для фильтрации дублирующихся данных.
const source = Rx.Observable.from([1, 2, 3, 2, 4, 3]);
const result = source.distinct();
result.subscribe(x => console.log(x));
Окончательные результаты работы программы: 1, 2, 3, 4, а повторяющиеся числа отфильтровываются напрямую.
filter
определение:
public filter(predicate: function(value: T, index: number): boolean, thisArg: any): Observable
Такому базовому нечего вводить, с массивом мы понимаемfilter
Метод ничем не отличается, просто используйте место, где он несовместим.
const source = Rx.Observable.from([1, 2, 3, 2, 4, 3]);
const result = source.filter(x => x !== 3);
result.subscribe(x => console.log(x));
В результате программа работает в дополнение к значению, отличному от 3.
first
определение:
public first(predicate: function(value: T, index: number, source: Observable<T>): boolean, resultSelector: function(value: T, index: number): R, defaultValue: R): Observable<T | R>
выдается только источникомObservable
Первое из выданных значений (или первое значение, удовлетворяющее условию).
Это похоже на вышеизложенное, и вы можете понять это в основном, прочитав введение, поэтому я не буду здесь вдаваться в подробности.
take
определение:
public take(count: number): Observable<T>
только источник излученияObservable
N значений, первоначально выпущенных(N = count)
.
Можно сказать, что этот оператор появлялся много раз раньше, и он довольно распространен, он используется для управления только определенным количеством значений, которые необходимо получить, за которыми следуетinterval
Этот вид сотрудничества, который будет продолжать отправлять данные, может автономно контролировать, сколько значений требуется.
skip
определение:
public skip(count: Number): Observable
вернутьObservable
, ДолженObservable
ПрыгатьObservable
Выдаются первые N значений(N = count)
.
Например, если предположить, что этот источник данных отправляет 6 значений, вы можете использоватьskip
оператора, чтобы пропустить первое число.
const source = Rx.Observable.from([1, 2, 3, 2, 4, 3]);
const result = source.skip(2);
result.subscribe(x => console.log(x));
Результат печати: 3, 2, 4, 3, пропуская первые два числа.
Другие операторы фильтра
Официально предоставленных операторов довольно много, поэтому я не буду их здесь представлять по одному, если интересно, можете зайти на официальный сайт и проверить:оператор фильтра.
debounce
distinctKey
distinctUntilChanged
distinctUntilKeyChanged
elementAt
ignoreElements
audit
auditTime
last
sample
sampleTime
single
skipLast
skipUntil
skipWhile
takeLast
takeUntil
takeWhile
throttle
Комбинированный оператор
concatAll
определение:
public concatAll(): Observable
Как следует из названия, этот оператор немного похож на нашjs
Метод среднего массиваconcat
Для большегоObservable
Синтезируют один, но в нем есть пометка, что он серийный, то есть объединяет дваObservable
, подписчик сначала получит первое значение при получении значенияObservable
, после чего начинает получать последнийObservable
ценность .
const source1 = Rx.Observable.of(1, 2);
const source2 = source1.map(x => Rx.Observable.interval(1000).take(3));
const result = source2.concatAll();
result.subscribe(x => console.log(x));
Согласно приведенному выше текстовому введению, я считаю, что каждый должен в какой-то степени понять этот код.Да, смысл этого кода в том, что наш источник данных отправляет два числа и используетmap
Оператор возвращает новыйObservable
, в это время для того, чтобы абонент получил несколькоObservable
, затем используйтеconcatAll
Объедините его, и результаты, полученные конечным подписчиком, будут: 0, 1, 2, 0, 1, 2.
mergeAll
определение:
public mergeAll(concurrent: number): Observable
а такжеconcatAll
Разницы почти нет, разница только в том, что она параллельная, то есть объединенная кратнаяObservable
Данные отправляются в произвольном порядке.
combineLatest
определение:
public combineLatest(other: ObservableInput, project: function): Observable
Множественное числоObservables
создатьObservable
,ДолженObservable
значение по каждому входуObservable
рассчитывается по последнему значению .
Этот оператор света не так легко понять из введения, давайте объясним это на примерах.
const s1 = Rx.Observable.interval(2000).take(3);
const s2 = Rx.Observable.interval(1000).take(5);
const result = s1.combineLatest(s2, (a, b) => a + b);
result.subscribe(x => console.log(x));
Результаты печати: 0, 1, 2, 3, 4, 5, 6.
Сначала давайте посмотрим на этоcombineLatest
используется, это оператор экземпляра, и здесь демонстрируется преобразованиеs1
а такжеs2
Объединены вместе, и второй параметр должен быть передан в обратном вызове для обработки объединенного значения. Поскольку здесь мы объединяем только два параметра, мы получаем толькоa
,b
Два параметра, возвращаемое значение функции обратного вызова — это значение, полученное подписчиком.
Из результатов мы ничего не видим, в основном потому, что процесс выглядит следующим образом:
-
s2
отправляет 0, а на этот разs1
Если значение не отправлено, обратный вызов, который мы передаем, не будет выполнен, и подписчик не получит значение. -
s1
отправляет 0, аs2
Последнее отправленное значение равно 0, поэтому вызывается функция обратного вызова, передаются эти два параметра, и, наконец, подписчик получает -
s2
отправляет 1, аs1
Последнее отправленное равно 0, поэтому результат равен 1. -
s1
отправляет 1, аs2
Значение последнего передаваемого составляет 1, результат составляет 2. -
s2
отправляет значение 2, аs1
Последнее отправленное значение было 1, поэтому результат равен 3. -
s2
отправляет значение 3, аs1
Последнее отправленное значение было 1, поэтому результат равен 4. - ...повторите вышеуказанные шаги.
Вот записка, мы найдем
s1
,s2
В какой-то момент данные будут отправлены одновременно, но это также будет иметь последовательность, поэтому на данный момент это зависит от того, кто определяет их первым и кто отправит их первым.Вы также должны быть в состоянии найти это явление из вышеуказанные шаги.
На самом деле между объединенными источниками существует отношение зависимости, то есть, если оба источника отправят хотя бы одно значение, то подписчик получит сообщение, и сигнал окончания не будет отправлен, пока два источника не будут отправлены.
zip
определение:
public static zip(observables: *): Observable<R>
поставить несколькоObservable
объединить, чтобы создатьObservable
,ДолженObservable
Значение определяется всеми входамиObservables
Значения рассчитываются последовательно. Если последним аргументом является функция, эта функция используется для вычисления окончательного выданного значения, в противном случае возвращается массив, содержащий все входные значения по порядку.
С точки зрения непрофессионала, расчет выравнивания последовательности будет выполняться между несколькими источниками, что аналогично предыдущему.combineLatest
Есть разница.
Без лишних слов, вот код:
const s1 = Rx.Observable.interval(1000).take(3);
const s2 = Rx.Observable.interval(2000).take(5);
const result = s1.zip(s2, (a, b) => a + b);
result.subscribe(x => console.log(x));
Результаты печати: 0, 2, 4.
Как это понять? Прежде всего, давайте запомним предложение. Числа, используемые для расчета между несколькими источниками, выровнены по порядку, то естьs1
первое число выровнятьs2
Первое число, это вычисление взаимно однозначного соответствия, которое в конечном итоге получает абонент, - это передача нескольких выровненных чисел в вызов, который мы вызываем.zip
Последняя функция обратного вызова, то есть результат, который используется для вычисления значения и, наконец, возврата пользователю, это необязательно.
После того, как любой из двух источников закончится, целое будет сигнализировать об окончании, потому что нет последующих чисел, которые можно было бы выровнять.
startWidth
определение:
public startWith(values: ...T, scheduler: Scheduler): Observable
вернутьObservable
Сначала выдает элементы, указанные в качестве параметров, а затем выдает источникObservable
Товар выдан.
Как вы это понимаете?Это на самом деле хороший пример.Например,есть цепочка засахаренных боярышников,все цвета одного цвета.Вам не кажется, что это хорошо выглядит,поэтому вы кладете несколько засахаренных боярышников разных цветов впереди из цепочки засахаренных орехов. Вы съедите засахаренные орехи, которые вы вставили спереди.
const source = Rx.Observable.interval(1000).take(3);
const result = source.startWith(666)
result.subscribe(x => console.log(x));
Результат печати: 666, 0, 1, 2.
Легко ли это понять?
switch
определение:
public switch(): Observable<T>
Подписываясь только на последние выпущенные внутренниеObservable
, высший порядокObservable
Преобразовать в первый порядокObservable
.
Для использования этого оператора мы представили его ранееswitchMap
Этот оператор преобразования уже упоминался, что эквивалентноmap
+switch
=switchMap
.
Возьмите каштан:
const btn = document.createElement('button');
btn.innerText = '我要发言!'
document.body.appendChild(btn);
const source = Rx.Observable.fromEvent(btn, 'click');
const source2 = source.map(x => Rx.Observable.interval(1000).take(3));
const result = source2.switch();
result.subscribe(x => console.log(x));
Эффект приведенного выше кода такой же, какswitchMap
Последовательно, когда пользователь нажимает кнопку, он начинает отправлять данные.Если передача данных не завершена, нажмите кнопку еще раз, чтобы начать новый процесс передачи данных и напрямую отказаться от исходного процесса передачи данных.
другие комбинаторы
Портал официального сайта:Комбинированный оператор
combineAll
concat
exhaust
forkJoin
merge
race
withLatestFrom
zipAll
многоадресный оператор
Портал официального сайта:многоадресный оператор
cache
multicast
publish
publishBehavior
publishLast
publishReplay
share
Быть совершенным...
оператор обработки ошибок
Портал официального сайта:оператор обработки ошибок
catch
retry
retryWhen
Быть совершенным...
оператор инструмента
Портал официального сайта:оператор инструмента
do
delay
delayWhen
dematerialize
finally
let
materialize
observeOn
subscribeOn
timeInterval
timestamp
timeout
timeoutWith
toArray
toPromise
Быть совершенным...
Условия и логические операторы
Портал официального сайта:Условия и логические операторы
defaultIfEmpty
every
find
findIndex
isEmpty
Быть совершенным...
Математические и агрегатные операторы
Портал официального сайта:Математические и агрегатные операторы
count
max
min
reduce
Быть совершенным...
Суммировать
В целом, дляRxJS
Эта форма потока данных очень удобна для поддержки сложных данных в нашей повседневной работе и с точки зрения многих сложных операций с данными.RxJS
Это может дать нам множество операторов, повышающих эффективность, а также новую идею манипулирования данными.
мы можем поставитьRxJS
Метафора как некое событие, которое может быть испущеноlodash
Библиотека инкапсулирует много сложной логики операций, позволяя нам выполнять преобразование данных и операции более элегантным способом во время использования.
Справочная статья
Руководство для начинающих по реактивному программированию - простой для понимания RxJS
История рыбака и Rxjs, на этот раз я научу вас Rxjs, которые должен знать интерфейс