简介

本文的读者受众

正准备学习Angular的人

想要知道Rx和RxJS相关知识的人

这篇文章是什么?

Angular使用RxJS标准库来有效地实现异步处理。

为了使用好 RxJS,需要考虑到与传统编程的不同之处。

就我而言,在什么都不知道的状态下阅读官方文档,我也不明白它的优势或具体用法。

不能理解的最大因素是我并没有形成RX的概念印象。

如果我从一开始就拥有这个概念印象,我认为我的学习会更顺利...... orz

所以在这篇文章中

我想现在开始使用Angular 6,但我还需要学习一个名为RxJS的库...

我想学习Rx,但我不知道从哪里开始

我想知道Rx是什么

将以这些方向,对RxJS使用的优点和他的概念、经常使用的方法进行解释。

RxJS

反应式扩展

Reactive Extensions(Rx)是,一个使用可观察数据序列和类LINQ样式的请求运算符,来创建(实现)异步及基于事件程序的技术库。

数据序列,拥有各种形式的存在。例如来自文件和Web服务的数据流,对Web服务的请求,系统通知以及用户操作的事件。

在简单阅读完上面链接内容后,继续以下内容

在Angular中使用RxJS的优点

Rx的世界中,处理的值并非固定,而是可以不断变化的数据流。

您可以在流中放置任何内容,例如用户操作的事件值活API响应结果等异步值,或数字和字符串等同步值。

任何值都可以在数据流中流入,Rx提供的通用格式进行数据的加工和时机的处理。

无论是事件还是API响应,您都可以使用相同的格式并通过便捷的代码段编写外观漂亮的代码。

这是使用Rx的最大好处。

因为JavaScript缺少用于操作数组和对象的标准API,所以我认为有很多机会使用名为lodash的库。

我认为Rx是Promise版的 lodash。

我称之为“时序处理”的是具体的以下实现。

控制高速连续的事件在每50ms发生

控制经常出现浏览器滚动控件

最后一次检测到事件后100毫秒

频繁出现的表单相关处理

事件在一定时间内发生过多次

控制双击等

在Angular ( SPA )中,时序相关的处理是很频繁的,如果每次都使用标准的 setTimeout 等方法实现的话,会有很多性能的浪费,而且代码也会变得极其难以阅读、理解。

通过使用RxJS,您可以将所有数据的合并、过滤、映射与时间轴的处理,轻松地放在一起实现。

Rx的印象

理解事物最重要的是印象的转换。

在本章中,我们将之前所罗列的Rx概念升华为印象。

这次我为那些根本不了解Rx的人做了一个简单的故事。

通过跟踪这个故事,我认为您可以学习到Rx的粗略概念。

在夏季时,有一条流淌桃子的河流( stream )

当然,除了桃子 ( value ) 以外也有魚 ( value )在流动。

在秋、冬、春时不会流淌桃子

您想利用这条神秘的河流,制造出材料成本为0的桃子罐头,然后贩卖赚大钱。

因此,我们需要建立一个系统,可以自动从河流中收集 ( filter )桃子、将其转换成桃子罐头 ( map )

系统的运行需要消耗电力

夏天的时候运行系统 ( subscribe )

夏天以外的时候不会有桃子,所以要关闭系统( unsubscribe ),以便他不消耗不必要的电力

Rx最重要的概念为“流”,所以经常用河流做比较。

现实中的河流,在没有我们做任何事情的情况下也会继续自由地流动。

像上面的故事中的一样,管理者打开装载的开关,监视 ( subscribe ) 河流、在罐头制造装置 ( operators ) 接收桃子( value ) 时,执行期望的处理。

Rx初学者刚开始经常遇到的问题是,因为忘记使用subscribe,而一直在查找值不流出的原因。

但是,如果您从一开始就能想到故事,就不会把时间浪费在这种类似的错误上。

此外,故事中出现的电力,就现实而言也就是客户端的CPU资源。与每个月发生的电费不同,内存泄漏经常出现在债务堆积的情况下。

因此,当您销毁组件时,请务必记住取消订阅内部订阅的流。

最后,将此故事转换为实际代码如下所示:

private subscription: Subscription;

ngOnInit() {

this.subscription = of('桃子', '鲤鱼').pipe(

filter(v => v === '桃子'),

map(v => v + '罐头')

).subscribe(console.log);

}

ngOnDestroy() {

this.subscription.unsubscribe();

}

桃子罐头

RxJS的概念总结

我认为可以在上一章的故事中大致理解Rx的概念,但我将再次回到原文。

在官方指南中,Rx库由以下公式表示:

Rx = Observables + LINQ (Operators) + Schedulers

正如我前面提到的,Observables是河流,事件,异步处理等的可观察对象,也是流的起点。

此外,Operators 可以被视为决定如何处理流中流动值的设备。

一旦订阅后,您可以使用反应式编程执行一系列流处理。

Subject

Subject类经常以各种方式使用,例如在Rx的逻辑中通知或临时存储值。

Subject结合上面的例子来说,类似于大坝。

大坝连接到河流,可以观察从大坝流出的价值,另外,也可以从外部设定值。

他就像流版的变量一样。

Subject有很多种类型,所以不能一概而论,但我认为它的概念印象是下面的图像。

重复出现的 Observable 和 Operators

如果上面说的已经全部理解的话,之后再有什么样的川 ( Observable ) 、什么样的装置( Operators ) 、剩下的工作仅仅是记住它们罢了。

这一次,我试图整理一个简单的使用场景,专注于我经常使用的东西。

此列表优先考虑具体的用途和印象,因为如果每个文本中都包含详细说明,则文字数量将是巨大的。

有关详细用法,请参阅官方文档。

Observable

from

将Promise 或者 iterator 的值 ( string、array 等 ) 转换为 Observable

使用例:处理API响应结果并检索所需的值

from(

fetch('https://jsonplaceholder.typicode.com/posts/1')

.then(r => r.json())

).map(v => v. userId).subscribe(console.log);

// 1

fromEvent

将event转换为 Observable

使用例:双击的捕捉

const click$ = fromEvent(document, 'click');

click$.subscribe(console.log);

merge

合并流动的值

使用场景:将各种事件合成为一个触发器

const click$ = fromEvent(targetElement, 'click');

const mouseover$ = fromEvent(targetElement, 'mouseover');

merge(click$, mouseover$).subscribe(() => {

// 期望的处理

});

of

将值转换为 Observable

使用场景:测试、确认用、流分裂或结合时的搭配

const hoge$ = of(1, 2, 3);

const huga$ = fromEvent(document, 'click');

merge(hoge$, huga$).subscribe(console.log);

interval

定时流动的值

使用场景:显示已用时间

this.count$ = interval(1000);

// wait 1sec

// 0

// wait 1sec

// 1

// wait 1sec

// 2

// ...

count: {{ count$ | async }}

concat

保存流的顺序并结合

使用场景:在应用中保存缓存内容和API响应的合成,并立即显示缓存 → 切换到准确的数据

this.article$ = concat(this.store.select(getSelectArticle), this.articleDb.findByKey(articleKey));

Operators

tap ( 旧 do )

在不影响流的情况下进行任何处理

使用场景:日志显示

stream$

.pipe(

tap(console.log),

tap(console.warn),

tap(console.error),

)

.subscribe();

map / pluck

流的値的加工・转换・抽出

使用场景:处理API响应结果(抽出需要的值)

const apiResponse$ = of({ userId: 1, body: 'hoge huga piyo' });

const userId$ = apiResponse$.pipe(map(v => v.userId));

// ---------------------------------------------------

// 如果只想要取得值,可以使用pluck,让代码更简洁

const userId$ = apiResponse$.pipe(pluck('userId'));

filter

过滤值

使用场景:重定向事件时显示加载进度条

const routerEvent$ = this.router.events;

routerEvent$

.pipe(filter(e => e instanceof NavigationStart))

.subscribe(() => this.store.dispatch(new ShowLoadingSpinnerAction()));

skip

跳过值

使用场景:跳过组件生成后联动处理

// 跳过第一次流动的值,因为它不是用户操作更改的值

this.route.params.pipe(pluck('categoryId'), skip(1)).subscribe(categoryId => {

console.log(`changed categoryId: ${ categoryId }`);

});

scan

使用以前的值

使用场景:无限滚动条的项目列表管理

this.items$ = nextItemSubject$.scan((acc, curr) => {

return acc.concat(curr);

}, []);

take

确定值流动的次数

使用场景:只使用变动值的最初 x 回

// 如果不使用take(1) 的话,每回store值更新的时候,都会调用API

this.store.select(getUserId).pipe(

take(1),

concatMap(userId => this.apiService.get(userId))

).subscribe();

startWith

指定最初流动的值

使用场景:显示经过的时间(改良版)

※ 如果仅使用 interval ,则第一秒将不会显示任何内容。

this.count$ = interval(1000).pipe(map(v => v + 1), startWith(0));

// 0

// wait 1sec

// 1

// wait 1sec

// 2

// ...

count: {{ count$ | async }}

takeUntil

值流动时的暂停处理

使用场景:在销毁组件时通过Subject发送结束流的通知

※ 但请注意、这篇文章 介绍的内存泄露

private onDestroy$ = new Subject();

ngOnInit() {

interval(1000).pipe(takeUntil(this.onDestroy$)).subscribe(console.log);

}

ngOnDestroy() {

this.onDestroy$.next();

}

concatMap

将值转变成Observable 后合并(执行中的处理结束后转到下一个操作处理)

使用场景:使用API1响应结果调用API2

switchMap

将值转变成Observable 后合并(下一个値过来时,中断正在执行的处理)

使用场景:实现 auto complete 功能

debounceTime

弃掉在两次输出之间小于指定时间的发出值

使用场景:实现 auto complete 功能

this.autoCompleteList$ = this.form.valueChanges.pipe(

debounceTime(100),

switchMap(input => this.apiService.get(input)),

);

throttleTime

控制值流动的速度

使用场景:控制滚动条事件

fromEvent(window, 'scroll').pipe(throttleTime(50)).subscribe(console.log);

withLatestFrom

与合并后流最新的值进行合并

使用场景:将点击的用户ID作为GA事件发送

fromEvent(targetElement, 'click').pipe(

withLatestFrom(this.store.select(getUserId))

).subscribe(([_, userId]) => {

this.analyticsService.sendEvent({ category: 'test', action: 'click', userId });

})

combineLatest

如果对主流和合成流都进行了更改,则会发送每个流的最新值

使用场景:表单输入值和store信息的合并

this.form.valueChanges.pipe(

combineLatest(this.store.select(getUserId))

).subscribe(([input, userId]) => {

console.log(`用户userId( ${ userId } ) 输入${ input } 中..`);

});

image

publish, share, refCount...etc

cold流转化为hot流

cold / hot 的概念在这篇文章 中介绍

使用场景:使用API1响应结果并行执行API2和API3

※ 将 API1 流 hot 化后,可防止多次调用API1

const userId$ = from(fetch('https://jsonplaceholder.typicode.com/posts/1').then(r => r.json())).pipe(

pluck('userId'),

publishReplay(1),

refCount()

);

userId$.concatMap(userId => this.api2Service.get(userId)).subscribe(console.log);

userId$.concatMap(userId => this.api3Service.get(userId)).subscribe(console.log);

关于RxJS6的导入

Observable、Subject 以及 Subscription

import { Observable, concat, Subject, Subscription } from 'rxjs';

Operators

import { map, tap } from 'rxjs/operators';

结束

image

翻译自

angular6 mysql_从Angular6开始入门RxJS6相关推荐

  1. 卸载阿里云服务器的mysql_阿里云服务器入门教程

    1.购买 登录官网查看云服务器购买列表,购买时选择地区.操作系统镜像等,购买云服务器后会发送短信通知,这里只列出一个: [阿里云]尊敬的用户:您的云服务器ECS创建成功(实例名称:xxxxxxxxxx ...

  2. dsl mysql_极简Querydsl入门

    1 数据库准备 使用MySQL数据库. 1.1 创建名为learnsql的数据库 建库语句 create datebase learnsql; 使用刚刚创建的learnsql数据库 use learn ...

  3. angular框架简介基础与使用(全文2w8字)前端框架angular

    写在前面 本文的所有内容,可以在我的博客上看到,下面是地址.建议去博客看,因为csdn的这篇图片我没上传. 可以转载,但请注明出处 我的博客-点击跳转 https://numbrun.gitee.io ...

  4. 【CuteJavaScript】Angular6入门项目(1.构建项目和创建路由)

    本文目录 一.项目起步 二.编写路由组件 三.编写页面组件 1.编写单一组件 2.模拟数据 3.编写主从组件 四.编写服务 1.为什么需要服务 2.编写服务 五.引入RxJS 1.关于RxJS 2.引 ...

  5. Angular6入门

    一. 脚手架安装 全局安装脚手架: npm install -g @angular/cli复制代码 创建新项目: ng new my-app(项目名)复制代码 转到项目目录: cd my-app复制代 ...

  6. Angular6入门学习

    Anagular学习 创建Anagular快捷方式 全局脚手架 npm i -g @angular/cli 创建项目 ng new myapp 创建组件 ng generate component 组 ...

  7. angular6入门实战,环境搭建、添加组件、服务、路由和HTTP

    目录 一.新建web项目 二.启动项目 三.添加表格,css控制隔行变色 四.创建组件 五.显示列表 创建模拟数据 导入 用* ngFor 列出 使用* ngIf 隐藏空白详细信息 设置所选样式 添加 ...

  8. Angular6 + Ng-Zorro项目开发总结(一)

    项目概述 开发一个多功能平台,具有展示产品,申请服务开通,申请记录查看等功能,与公司内部系统相连接,初步功能较为单一, 后期可能会扩展新功能. 项目选型 由于上一个项目选择的Abp框架,配合使用的是a ...

  9. angular6 mysql_angular6之路由

    对于前端单页应用,路由一般由前端管理.在angular6中路由通过@angular/router模块实现. 1.在app的根目录下新建app-routing.module.ts,需要引入RouteMo ...

最新文章

  1. 开发js插件之所遇--02[DOM]
  2. Spring——AOP配置时的jar包异常
  3. linux c 实现uname命令
  4. 【深度学习】自然场景中文汉字数据集下载
  5. HDU 1175 连连看
  6. C语言 嵌入式 面试小知识点(一)
  7. 做大公司的螺丝钉 vs 当小公司的多面手
  8. Android 系统性能优化(12)---MTK 平台UX性能分析方法
  9. 实验三 lr分析器的设计与实现_实验室规划设计趋势之一灵活性|无风管通风柜的灵活性是如何实现的?...
  10. FFMPEG结构体分析:AVCodec
  11. linux调度器(十)——调度器/proc信息解读
  12. 数据结构课程设计实验报告
  13. PDF417打印后扫描不出来(记录)
  14. 【IoT】产品设计:OEM、ODM、EMS 的区别是什么?
  15. 基于python3.5+opencv+windowsAPI图像识别实现的连连看外挂
  16. c3p0-0.9.1.2.jar与c3p0-0.9.5.2.jar
  17. 无处安放         (此刻心情)
  18. 3Dmax Bones骨骼学习记录一
  19. MATLAB大小写字符的转换
  20. iOS10 配置ATS

热门文章

  1. 计组学习总结(被逼无奈)
  2. Oracle主键自增的批量插入
  3. 生成DOTA格式的数据集
  4. 动手学深度学习--课堂笔记图片分类数据集
  5. python中的数组下标
  6. Maven的生命周期
  7. 水下目标检测之数据集和数据增强方法
  8. JS获取当前节点的兄弟/父/子节点
  9. Qt分割条splitter,画出来比写代码方便
  10. My97DatePicker