RxJS: применение asyncScheduler в качестве аргумента по сравнению с операторомObservOn
Какой выбрать?
Keywords: RxJS, Schedulers.
Pre-requisites: you should have basic knowledge about the browser event-loop, RxJS, Observables and Schedulers.
Если вы не знакомы с планировщиками в RxJS, в моей статье есть краткий обзор. статья о планировщике очереди. Вкратце — asyncScheduler позволяет выводить каждое значение в отдельном mаcrotask (с точки зрения задач очереди событийного цикла браузера). Если вы хотите узнать больше о том, как работает event-loop (микрозадачи, макрозадачи, очередь) — посмотрите это замечательное видео и прочитай это отличная статья.
Если вы хотите применить планировщик к наблюдаемой последовательности, вы можете сделать это двумя способами:
- Некоторые заводские функции (например, из, из, диапазони т. д.) имеют необязательный SchedulerLike параметр Как это:
описание диапазона на rxjs-dev.firebaseapp.com
Например:
of(1,2,3, asyncScheduler)
- Вы можете применить его с наблюдать на оператор:
Например:
of(1,2,3).pipe(observeOn(asyncScheduler))
Оба этих решения заставляют каждую отдельную передачу данных происходить в отдельном m.аcrotask (поэтому каждая эмиссия ставится в очередь в цикле событий браузера mаочередь crotasks).
Но делают они это немного по-другому. Обычно вам не нужно беспокоиться об этом, но в некоторых конкретных случаях это различие может быть важным.
Давайте подробно рассмотрим, как работает каждое решение:
- Планировщик аргументов:
of(1,2,3, asyncScheduler).subscribe(console.log)
Шаги:
- из выдает первое значение согласно планировщику (следующие mаcrotask в этом примере)
- Он помещает следующее значение в очередь планировщика (еще один mаКротаск)
- Шаги 1 и 2 повторяются с каждым из следующих выбросов.
Поскольку в очереди цикла событий браузера запланирована только следующая эмиссия значений, теоретически существует вероятность того, что другие mакрозадачи могут выполняться между создаваемыми значениями.
- Что насчет наблюдать на путь?
of(1,2,3).pipe(observeOn(asyncScheduler)).subscribe(console.log)
Шаги:
из производит все значения, они буферизуются
observeOn
оператор.observeOn
планирует все значения, но отдельно с указанным Планировщиком (отдельно mаcrotask в примере) и помещает соответствующие задачи в очередь событийного цикла.
Это означает, что все задачи эмиссии помещаются в очередь цикла обработки событий одна за другой, поэтому другие задачи не могут выполняться между ними.
Вы можете проверить эти утверждения в кодовая ручка.
Вот наш код планировщика аргументов:
Вот тот же код в суть
В обработчике подписки я использую console.log
чтобы напечатать значение для текущего mаКротаск. Также Promise.resolve.then
используется для печати значения в mяcrotask сразу после текущего mаКротаск. И наконец, setTimeout
печатает значение в другой макрозадаче в соответствии с порядком очереди цикла обработки событий.
И это его вывод:
Хорошо, так что мы имеем здесь? ‘Мазначение crotask 1′ печатается после ‘Mязначение кротаска 2′. И что? Это означает, что до того, как OF observable сделает первую эмиссию, она уже запланировала следующую эмиссию в очереди событийного цикла.
Хорошо, теперь давайте запустим код с помощью asyncScheduler
применяется observeOn
оператор:
Планировщик с оператором ObserveOn суть
Теперь вывод немного другой:
Первый of
observable выдал все значения. затем observeOn
запланировал все выбросы в отдельные макрозадачи и поместил их в очередь событийного цикла. Вот почему все выходные данные setTimeout console.log из обработчика подписки запускаются в самом конце — потому что очередь цикла событий уже содержала запланированные задачи из «observeOn».
Вывод: Применение планировщика в качестве аргумента фабричной функции намного эффективнее с точки зрения ресурсов ЦП/памяти, если количество выдаваемых значений существенно. Поэтому, если вы планируете подать заявку asyncScheduler
к такому выражению, как
range(0, 1e10).pipe(tap(v =\> doSomething(v)))
то вы определенно должны предпочесть применять его в качестве диапазон аргумент.
// non-efficient
range(0, 1e10).pipe( tap(v => doSomething(v)), observeOn(asyncScheduler))
// efficient
range(0, 1e10, asyncScheduler).pipe( tap(v => doSomething(v)))
Надеюсь, вам понравилась эта статья. Пожалуйста, оставляйте комментарии с вашими личными вариантами использования планировщиков RxJS!
Packtpub.com и я подготовили целый RxJS обзорный курс со многими другими подробностями о том, как вы можете решать свои повседневные задачи разработчика с помощью этой удивительной библиотеки. Взглянем!
Я хотел бы сказать большое спасибо Николас Джеймисон , Ларс Гируп Бринк Нильсен, Тодд Палмер а также Макс Волшебник К за просмотр этого поста.
Вы можете проверить мои другие статьи на средний