freeCodeCamp/guide/russian/angular/reactive-extensions/index.md

26 KiB
Raw Blame History

title localeTitle
Reactive Extensions Реактивные расширения

Реактивные расширения в угловом

мотивация

Реактивные расширения для 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 и наоборот. Обычно это означает, что они могут стоять автономно, а не полностью функционировать без друг друга.

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

Наблюдаемые

Для того, чтобы быстро повторить, Observable можно наблюдать с. Это позволяет Observable обеспечивать обратную связь с зависимостями на основе потока данных. В RxJS Observable - это собственная фабричная функция, используемая для создания объектов Observable . Их основной план состоит в следующем.

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 . Затем потребители уведомляются при получении данных.

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 . Это означает, что данные могут производить один раз и выделять все в одной операции.

Функции обратного вызова - это не единственный способ использования данных. Наблюдатели могут цеплять друг в друга как производители и потребители.

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 операторов вместе. Результаты предыдущего оператора переходят в следующий раунд до конечного оператора. Полученные данные затем исходят из наблюдаемого потока.

Обратите внимание на стандартный пример ниже. Используйте его для сравнения для воздействия каждого оператора на испускаемый поток данных.

import { Observable, from } from 'rxjs'; 
 
 const stream: number[] = [1, 2, 3, 4, 5]; 
 
 const observable: Observable<number> = from(stream); 
 observable.subscribe((val: number) => console.log(val)); 
 
 // console output 
 /* 
 1 
 2 
 3 
 4 
 5 
 */ 

.from преобразует массив в объект Observable который вызывает .next для каждого элемента массива. Функция .pipe принимает любое количество аргументов в качестве операторов массива. Здесь каждый оператор реализуется. Операторы выполняют на упорядоченных данных в порядке их реализации в качестве аргументов для .pipe .

уменьшить

.reduce минимизирует поток данных в одно значение перед испусканием.

import { reduce } from 'rxjs/operators'; 
 
 const stream: number[] = [1, 2, 3, 4, 5]; 
 
 const observable: Observable<number> = from(stream).pipe( 
  reduce((accum, val) => (accum + val)) 
 ); 
 observable.subscribe((val: number) => console.log(val)); 
 
 // console output 
 /* 
 15 
 */ 
Фильтр

.filter обрезает поток, исключая значения потока, которые не удовлетворяют его условиям.

import { filter } from 'rxjs/operators'; 
 
 const stream: number[] = [1, 2, 3, 4, 5]; 
 
 const observable: Observable<number> = from(stream).pipe( 
  filter((val) => (val % 2 === 0)) // filters out odd numbers 
 ); 
 observable.subscribe((val: number) => console.log(val)); 
 
 // console output 
 /* 
 2 
 4 
 */ 
карта

.map и преобразует каждое текущее значение потока.

const stream: number[] = [1, 2, 3, 4, 5]; 
 
 const observable: Observable<number> = 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 . API предоставляет массив из 100 элементов на асинхронный GET .

// ./models/post.model.ts 
 
 export interface Post { 
  userId: number; 
  id: number; 
  title: string; 
  body: string; 
 } 
// ./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<any> { 
    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)) 
      ); 
  } 
 } 
// ./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: ` 
  <h1>Request User Posts</h1> 
  <span>User: </span><input #userInput> 
  <button (click)="requestForPosts(userInput.value)">REQUEST</button> 
  <hr> 
  <ul> 
    <div *ngIf="userPosts"> 
      <div *ngFor="let post of userPosts"> 
        <h3>{{ post.title }}</h3> 
        <p>{{ post.body }}</p> 
      </div> 
    </div> 
    <h3 *ngIf="!userPosts">No posts shown...</h3> 
  </ul> 
  ` 
 }) 
 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 становится пригодной для использования. Его операторы эффективно преобразуют данные из потока в результаты. Кроме того, наблюдатели могут подписаться на результаты, увеличивая общую переносимость данных.

источники

Ресурсы