--- title: Reactive Extensions localeTitle: Реактивные расширения --- # Реактивные расширения в угловом #### мотивация Реактивные расширения для JavaScript (RxJS) - это библиотека для _наблюдаемых_ потоков данных. RxJS устанавливает с помощью Angular при выполнении командной строки `ng new [name-of-application]` . Это использует интерфейс командной строки с угловым интерфейсом (CLI). RxJS дополняет процесс упорядочения данных через `Observable` . Объект `Observable` облегчает поток _итерируемых_ данных. Потоки данных не являются основным прецедентом. В конце концов, поток данных передает параллельные потоки событий. События выдают, поэтому приложение знает, когда поступают данные. Хотя потоки событий формируют ядро ​​того, что добавляет RxJS, эта статья также относится к ним как к потокам данных. Потоки выполняются либо синхронно (немедленно), либо асинхронно (сверхурочно). RxJS легко справляется с обоими случаями через поток данных `Observable` . Тем не менее строгая асинхронность. Работа с _встроенной_ памятью, _повторяющиеся_ данные происходят немедленно, в то время как для получения внешних данных требуется время. Угловая поддержка библиотеки RxJS, так что она может обрабатывать оба варианта использования с потоками данных. #### Реактивное программирование Прежде чем погрузиться в воду, важно понять парадигму, поддерживающую библиотеку RxJS. Как уже упоминалось, он работает через объект `Observable` который оптимизирует данные, генерирующие события. Функции RxJS вокруг базы `Observable` . Вся его библиотека дополняет то, что она может сделать. RxJS включает и другие объекты, включая `Subject` , `Subscription` и `Observer` . Каждый из них является собственным вариантом базы `Observable` . RxJS возникла из парадигмы реактивного программирования. Эта парадигма ввела _наблюдаемую_ картину. В ней существует эта ключевая идея: один `Observable` излучает в то время как все его `Observer` s получить уведомление. `Observer` _подписываются_ на `Observable` чтобы получать уведомление. Это уведомление может означать несколько вещей. Это может означать изменение данных или прибытие данных, как это обычно указывается в этой статье. Он может сигнализировать об изменении какой-либо части приложения, которая влияет на `Observer` s. Эта _наблюдаемая_ модель также стремится отделить понятия. `Observable` должен функционировать без каких-либо `Observer` и наоборот. Обычно это означает, что они могут стоять автономно, а не полностью функционировать без друг друга. Если вам интересно, вы можете узнать больше об основах реактивного программирования, прочитав [эту статью в Википедии](https://en.wikipedia.org/wiki/Reactive_programming) . В этом разделе рассказывается о том, что необходимо для остальной части статьи. #### Наблюдаемые Для того, чтобы быстро повторить, `Observable` можно _наблюдать_ с. Это позволяет `Observable` обеспечивать обратную связь с зависимостями на основе потока данных. В RxJS `Observable` - это собственная фабричная функция, используемая для создания объектов `Observable` . Их основной план состоит в следующем. ```typescript import { Observable } from 'rxjs'; const observable = Observable.create((source) => { source.next(data); }); ``` `.next` передает данные при передаче события своим наблюдателям. An `Observable` эмитирует данные внутри своего `.create` обратного вызова с помощью `.next` . Он принимает один аргумент, представляющий данные для испускания. `Observable` еще не был внедрен в JavaScript. RxJS обеспечивает замену из своей библиотеки. Следующий шаг - наблюдатели. Чтобы сообщить функции или объекту _наблюдать_ `Observable` , используется следующий синтаксис: `observable.subscribe(observer)` . Другой способ взглянуть на это - `producer.subscribe(consumer)` . Наблюдаемые _производят_ данные, вызывая `.next` . Затем потребители уведомляются при получении данных. ```typescript import { Observable } from 'rxjs'; const observable = Observable.create((source) => { source.next("Hello"); source.next("World!"); }); observable.subscribe((word) => console.log(word)); // console output /* Hello World! */ ``` Два вызова `.next` происходят из обратного вызова `Observable` `.create` (производитель данных). Это приводит к двум отдельным выходам консоли от наблюдателя (потребителя данных). Два вызова `.next` представляют собой синхронный поток данных. Потоки концептуализируют данные как линейный поток в порядке. Он либо решает синхронно, либо асинхронно, в зависимости от доступности данных. Если данные, содержащие поток, легко доступны, он выполняется синхронно. В противном случае поток решает асинхронно сверхурочно. Порядок данных в любом случае всегда один и тот же в зависимости от вызова `.next` пределах наблюдаемого. `Observable` работает как очередь. Вызов `.next` на кусок данных подталкивает его к задней части очереди. После этого данные появляются с фронта. `Observable` потоки данных имеют огромное значение. Они детерминированы в своем порядке и разумно зависят от доступности данных. Кроме того, любое количество наблюдателей может _наблюдать_ за источником данных `Observable` . Это означает, что данные могут производить один раз и выделять все в одной операции. Функции обратного вызова - это не единственный способ использования данных. Наблюдатели могут цеплять друг в друга как производители и потребители. ```typescript const observableI = Observable.create((source) => { source.next("Hello World!"); }); const observableII = new Observable().subscribe((v) => console.log(v)); observableI.subscribe(observableII); // console output /* Hello World! */ ``` `.subscribe` находится в объекте `Observable` . Вы можете назвать его `Observable` как его источник (продюсер), а другой - как аргумент (потребитель). Данные могут проходить (излучать) через любое количество наблюдаемых. #### Реактивные расширения для JavaScript (RxJS) Потоковые данные хороши, но какова точка, если наблюдаемые не могут редактировать поток? Это где библиотека RxJS вступает в игру. Он предоставляет операторам, которые выполняют различные мутации в потоке данных. Угловые рычаги используют эти операторы для преобразования входящих данных. Разработчики могут обрезать любые ненужные данные из входящего потока с использованием операторов RxJS. Это экономит память и устраняет необходимость в дополнительной логике преобразования. RxJS предлагает отклонения от стандартного `Observable` например `Subject` , `Subscription` и `Observer` . Подумайте об этих отклонениях как о специальных ароматах традиционного `Observable` . Они не нужны, чтобы использовать библиотеку. Тем не менее, варианты, подобные `Subject` имеют невероятные прецеденты, превосходящие стандарт `Observable` . Эта статья придерживается стандартного `Observable` . Все операторы потока данных из RxJS работают через `Observable` . Многие операторы ядра RxJS были созданы из массивов JavaScript. Прототип объекта Array содержит много параллелей с библиотекой RxJS. Они иначе известны как «Дополнительно». Массивы представляют собой потоковые структуры, подобные наблюдаемым парам данных. Чтобы лучше понять операторы RxJS, в этой статье мы кратко рассмотрим расширения массива JavaScript. Каждый из функций почти идентичен своему RxJS-аналогу. Разница - это просто формат данных (итерируемый массив против итеративного потока). #### Дополнительно Массивы содержат множество полезных методов. Эти методы называются Extray Array. Все они существуют на прототипе объекта Array. В приведенном ниже списке содержится пять дополнений с параллелями RxJS. * `.reduce` * `.filter` * `.map` * `.every` * `.forEach` Для каждого примера массив выполняет итерацию над собой для получения конечного результата. `.reduce` минимизирует массив в одно значение. `.filter` массив с булевой оценкой. `.map` преобразует массив по элементам. `.every` оценивает true или false для всего массива в зависимости от логического условия. `.forEach` выполняет `.forEach` через элементы массива. Массирует потоки модели. Они находятся в порядке друг друга и повторяются один за другим. Наблюдает обтекание элементов данных своим наблюдателям аналогичным образом. Вот почему RxJS включает логическую копию каждого массива в своей библиотеке. Конечно, RxJS предоставляет больше возможностей своим операторам, чем Array Extras. #### Основные операторы RxJS Существует буквально целая библиотека для операторов RxJS. В этой статье рассматриваются те, которые перечислены ниже, которые вдохновили Extreme Array. * `.reduce` * `.filter` * `.map` * `.every` * `.forEach` Ничего не изменилось из предыдущего списка. Ваше понимание Extray Array относится к операторам RxJS. Единственный улов для этого - это функция, называемая `.pipe` которая увидит много пользы в следующих нескольких примерах. `.pipe` цепи RxJS операторов вместе. Результаты предыдущего оператора переходят в следующий раунд до конечного оператора. Полученные данные затем исходят из наблюдаемого потока. Обратите внимание на стандартный пример ниже. Используйте его для сравнения для воздействия каждого оператора на испускаемый поток данных. ```typescript import { Observable, from } from 'rxjs'; const stream: number[] = [1, 2, 3, 4, 5]; const observable: Observable = from(stream); observable.subscribe((val: number) => console.log(val)); // console output /* 1 2 3 4 5 */ ``` `.from` преобразует массив в объект `Observable` который вызывает `.next` для каждого элемента массива. Функция `.pipe` принимает любое количество аргументов в качестве операторов массива. Здесь каждый оператор реализуется. Операторы выполняют на упорядоченных данных в порядке их реализации в качестве аргументов для `.pipe` . ##### уменьшить `.reduce` минимизирует поток данных в одно значение перед испусканием. ```typescript import { reduce } from 'rxjs/operators'; const stream: number[] = [1, 2, 3, 4, 5]; const observable: Observable = from(stream).pipe( reduce((accum, val) => (accum + val)) ); observable.subscribe((val: number) => console.log(val)); // console output /* 15 */ ``` ##### Фильтр `.filter` обрезает поток, исключая значения потока, которые не удовлетворяют его условиям. ```typescript import { filter } from 'rxjs/operators'; const stream: number[] = [1, 2, 3, 4, 5]; const observable: Observable = from(stream).pipe( filter((val) => (val % 2 === 0)) // filters out odd numbers ); observable.subscribe((val: number) => console.log(val)); // console output /* 2 4 */ ``` ##### карта `.map` и преобразует каждое текущее значение потока. ```typescript const stream: number[] = [1, 2, 3, 4, 5]; const observable: Observable = from(stream).pipe( map((val) => (val + 1)) ); observable.subscribe((val: number) => console.log(val)); // console output /* 2 3 4 5 6 */ ``` ##### Задача: Every и ForEach Со знанием `.every` и `.forEach` как Array Extras, попробуйте реализовать их как операторов RxJS. Не стесняйтесь использовать предыдущие примеры для руководства. Немного практики проходит долгий путь после многих чтений! #### HTTP в угловом Этот раздел объединяет RxJS и Angular, чтобы показать, как они взаимодействуют. Как правило, услуга, предоставляемая Angular, обеспечит `Observable` . Поток данных `Observable` может затем мутировать с использованием операторов `.pipe` с `.pipe` . Угловой предоставляет услугу `HttpClient` через `@angular/common/http` `HttpClient` `@angular/common/http` . `HttpClientModule` также из `@angular/common/http` и экспортирует службу `HttpClient` . Корневой модуль приложения должен импортировать `HttpClientModule` . Это делает `HttpClientModule` _инъекционным в_ любом месте приложения. Служба `HttpClientModule` HTTP-запросы. Эти запросы являются асинхронными. Что делает их интересными для Angular, так это то, как обрабатывается запрос. `Observable` возвращается с каждым запросом. RxJS может убрать его оттуда. В следующем примере используется открытый API, созданный [Typicode](https://jsonplaceholder.typicode.com) . API предоставляет массив из 100 элементов на асинхронный `GET` . ```typescript // ./models/post.model.ts export interface Post { userId: number; id: number; title: string; body: string; } ``` ```typescript // ./services/json.service.ts import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable, from } from 'rxjs'; import { switchMap, map, filter, reduce } from 'rxjs/operators'; import { Post } from '../models/post.model'; @Injectable({ providedIn: 'root' }) export class JsonService { constructor(private http: HttpClient) { } getPostsByUserId(id: number): Observable { const trim$ = (stream) => from(stream) .pipe( filter((post: Post) => +post.userId === +id), map((post: Post) => ({ title: post.title, body: post.body })), reduce((accum: Post[], post: Post) => accum.concat([post]), []) ); return this.http.get("https://jsonplaceholder.typicode.com/posts") .pipe( switchMap((value) => trim$(value)) ); } } ``` ```typescript // ./components/example/example.component.ts import { Component } from '@angular/core'; import { JsonService } from '../../services/json.service'; import { Post } from '../../models/post.model'; @Component({ selector: 'app-example', template: `

Request User Posts

User:

    {{ post.title }}

    {{ post.body }}

    No posts shown...

` }) export class ExampleComponent { userPosts: Post[]; constructor(private json: JsonService) { } requestForPosts(id: number): void { this.json.getPostsByUserId(id) .subscribe((posts: Post[]) => { this.userPosts = posts.length > 0 ? posts : null; }); } } ``` `json.service.ts` создает `Observable` от имени `component.example.ts` . Компонент может подписаться на возвращаемый `Observable` . Только одно значение излучает к тому времени, когда `Observable` разрешает поток данных. Запрос `jsonplaceholder.typicode.com` дает один массив из 100 сообщений. Запрос через `HttpClient` дает `Observable` . Оператор `switchMap` возвращает другое `Observable` которое перезаписывает текущий поток. Переменная `trim$` хранит `Observable` как ее значение. Добавление `$` к переменной, используемой для хранения `Observable` s, является условным. `from` конвертирует массив из `jsonplaceholder.typicode.com` в 100-значение, излучающее `Observable` . Затем операторы RxJS просеивают каждую часть данных в потоке. Они удаляют значения потока, не относящиеся к запросу. Обрезка данных происходит таким образом, что значения потока остаются ненужными. Окончательные результаты снова объединяются в единый массив, который испускает его наблюдателям. В `component.example.ts` JsonService ссылается на метод, возвращающий только что описанный `Observable` . Этот метод вызывается при нажатии кнопки в шаблоне компонента. Поле ввода также в шаблоне предоставляет один аргумент `id` . При нажатии кнопки JsonService возвращает `Observable` который испускает один массив. `.subscribe` вызывает на возвращаемом `Observable` . Затем компонент устанавливает значение `userPosts` равным испускаемому массиву. Обнаружение углового изменения фиксирует изменение данных класса. Обновления шаблона и `*ngFor` обеспечивают, чтобы каждый элемент массива из `userPosts` отображал свой собственный элемент шаблона. #### Вывод RxJS обеспечивает ядро `Observable` вместе со своими операторами. Библиотека автоматически устанавливается из командной строки с помощью `ng new [name-of-app]` (Угловая CLI). Типы и операторы ядра RxJS загружаются соответственно в `rxjs` и `rxjs/operators` . Даже если вы не используете CLI, такие сервисы, как `HttpClient` , все еще пригодны для использования. Служба возвращает `Promise` вместо `Observable` если RxJS недоступен. Объект `Promise` является родным для JavaScript в отличие от `Observable` . Вероятно, это изменится в следующем официальном выпуске JavaScript. Тем не менее, в полной мере используйте RxJS! Любая итеративная структура может вместить `Observable` . С его помощью вся библиотека RxJS становится пригодной для использования. Его операторы эффективно преобразуют данные из потока в результаты. Кроме того, наблюдатели могут подписаться на результаты, увеличивая общую переносимость данных. ## источники * [Угловая команда. «Библиотека RxJS». _Google_ . Доступ к 5 июня 2018 года.](https://angular.io/guide/rx-library) * [Форбс, Эллиот. «Создание приложения реального времени с помощью Angular и Socket.io Tutorial». _TutorialEdge.net_ , 10 января 2017. Доступен 5 июня 2018 года.](https://tutorialedge.net/typescript/angular/angular-socket-io-tutorial) * [Команда RxJS. «Документация RxJS». _RxJS_ . Доступ к 5 июня 2018 года.](https://rxjs-dev.firebaseapp.com) * [Сукале, Райан. «Разница между субъектом Rxjs и наблюдаемым». _TutorialHorizon_ , 23 марта 2017. Доступен 5 июня 2018 года.](https://javascript.tutorialhorizon.com/2017/03/23/rxjs-subject-vs-observable) * [Сообщество Википедии. «Реактивное программирование». _Википедия_ , 2 июня 2018. Доступен 5 июня 2018 года.](https://en.wikipedia.org/wiki/Reactive_programming) ## Ресурсы * [Угловая документация](https://angular.io/guide) * [Угловая на GitHub](https://github.com/angular/angular) * [Угловая CLI](https://cli.angular.io) * [RxJS и угловой](https://angular.io/guide/rx-library) * [Реактивное программирование](https://en.wikipedia.org/wiki/Reactive_programming) * [Реактивные расширения для JavaScript](https://rxjs-dev.firebaseapp.com)