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 (микрозадачи, макрозадачи, очередь) — посмотрите это замечательное видео и прочитай это отличная статья.

Если вы хотите применить планировщик к наблюдаемой последовательности, вы можете сделать это двумя способами:

  1. Некоторые заводские функции (например, из, из, диапазони т. д.) имеют необязательный SchedulerLike параметр Как это:


описание диапазона на rxjs-dev.firebaseapp.com

Например:

of(1,2,3, asyncScheduler)
  1. Вы можете применить его с наблюдать на оператор:

Например:

of(1,2,3).pipe(observeOn(asyncScheduler))

Оба этих решения заставляют каждую отдельную передачу данных происходить в отдельном m.аcrotask (поэтому каждая эмиссия ставится в очередь в цикле событий браузера mаочередь crotasks).

Но делают они это немного по-другому. Обычно вам не нужно беспокоиться об этом, но в некоторых конкретных случаях это различие может быть важным.

Давайте подробно рассмотрим, как работает каждое решение:

  1. Планировщик аргументов:
of(1,2,3, asyncScheduler).subscribe(console.log)

Шаги:

  1. из выдает первое значение согласно планировщику (следующие mаcrotask в этом примере)
  2. Он помещает следующее значение в очередь планировщика (еще один mаКротаск)
  3. Шаги 1 и 2 повторяются с каждым из следующих выбросов.

Поскольку в очереди цикла событий браузера запланирована только следующая эмиссия значений, теоретически существует вероятность того, что другие mакрозадачи могут выполняться между создаваемыми значениями.

  1. Что насчет наблюдать на путь?
of(1,2,3).pipe(observeOn(asyncScheduler)).subscribe(console.log)

Шаги:

  1. из производит все значения, они буферизуются observeOn оператор.

  2. observeOn планирует все значения, но отдельно с указанным Планировщиком (отдельно mаcrotask в примере) и помещает соответствующие задачи в очередь событийного цикла.

Это означает, что все задачи эмиссии помещаются в очередь цикла обработки событий одна за другой, поэтому другие задачи не могут выполняться между ними.

Вы можете проверить эти утверждения в кодовая ручка.

Вот наш код планировщика аргументов:
суть
Вот тот же код в суть

В обработчике подписки я использую console.log чтобы напечатать значение для текущего mаКротаск. Также Promise.resolve.then используется для печати значения в mяcrotask сразу после текущего mаКротаск. И наконец, setTimeout печатает значение в другой макрозадаче в соответствии с порядком очереди цикла обработки событий.

И это его вывод:

Хорошо, так что мы имеем здесь? ‘Мазначение crotask 1′ печатается после ‘Mязначение кротаска 2′. И что? Это означает, что до того, как OF observable сделает первую эмиссию, она уже запланировала следующую эмиссию в очереди событийного цикла.

Хорошо, теперь давайте запустим код с помощью asyncScheduler применяется observeOn оператор:
планировщик gist2.png
Планировщик с оператором 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 обзорный курс со многими другими подробностями о том, как вы можете решать свои повседневные задачи разработчика с помощью этой удивительной библиотеки. Взглянем!

Я хотел бы сказать большое спасибо Николас Джеймисон , Ларс Гируп Бринк Нильсен, Тодд Палмер а также Макс Волшебник К за просмотр этого поста.

Вы можете проверить мои другие статьи на средний

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *