当前位置: 首页 > 编程日记 > 正文

# 30 天精通 RxJS (01):认识 RxJS

RxJS 是笔者认为未来几年内会非常红的 Library,RxJS 提供了一套完整的非同步解决方案,让我们在面对各种非同步行为,不管是 Event, AJAX, 还是 Animation 等,我们都可以使用相同的 API (Application Programming Interface) 做开发。

RxJS Logo

这是【30天精通 RxJS】的 01 篇,如果还没看过 00 篇可以往这边走:
30 天精通 RxJS (00): 关于本系列文章

在网页的世界存取任何资源都是非同步(Async)的,比如说我们希望拿到一个档案,要先发送一个请求,然后必须等到档案回来,再执行对这个档案的操作。这就是一个非同步的行为,而随着网页需求的复杂化,我们所写的 JavaScript 就有各种针对非同步行为的写法,例如使用 callback 或是 Promise 对象甚至是新的语法糖 async/await —— 但随着应用需求愈来愈复杂,撰写非同步的代码仍然非常困难。

非同步常见的问题

  • 竞态条件 (Race Condition)
  • 内存泄漏 (Memory Leak)
  • 复杂的状态 (Complex State)
  • 例外处理 (Exception Handling)

Race Condition

每当我们对同一个资源同时做多次的非同步存取时,就可能发生 Race Condition 的问题。比如说我们发了一个 Request 更新使用者资料,然后我们又立即发送另一个 Request 取得使用者资料,这时第一个 Request 和第二个 Request 先后顺序就会影响到最终接收到的结果不同,这就是 Race Condition。

Memory Leak

Memory Leak 是最常被大家忽略的一点。原因是在传统网站的行为,我们每次换页都是整页重刷,并重新执行 JavaScript,所以不太需要理会内存的问题!但是当我们希望将网站做得像应用程式时,这件事就变得很重要。例如做 SPA (Single Page Application) 网站时,我们是透过 JavaScript 来达到切换页面的内容,这时如果有对 DOM 注册监听事件,而没有在适当的时机点把监听的事件移除,就有可能造成 Memory Leak。比如说在 A 页面监听 body 的 scroll 事件,但页面切换时,没有把 scroll 的监听事件移除。

Complex State

当有非同步行为时,应用程式的状态就会变得非常复杂!比如说我们有一支付费用户才能播放的视频,首先可能要先抓取这部视频的资讯,接着我们要在播放时去验证使用者是否有权限播放,而使用者也有可能再按下播放后又立即按了取消,而这些都是非同步执行,这时就会各种复杂的状态需要处理。

Exception Handling

JavaScript 的 try/catch 可以捕捉同步的例外,但非同步的程式就没这么容易,尤其当我们的非同步行为很复杂时,这个问题就愈加明显。

各种不同的 API

我们除了要面对非同步会遇到的各种问题外,还需要烦恼很多不同的 API

  • DOM Events
  • XMLHttpRequest
  • fetch
  • WebSockets
  • Server Send Events
  • Service Worker
  • Node Stream
  • Timer

上面列的 API 都是非同步的,但他们都有各自的 API 及写法!如果我们使用 RxJS,上面所有的 API 都可以透过 RxJS 来处理,就能用同样的 API 操作 (RxJS 的 API)。

这里我们举一个例子,假如我们想要监听点击事件(click event),但点击一次之后不再监听。

原生 JavaScript

var handler = (e) => {console.log(e);document.body.removeEventListener('click', handler); // 结束监听
}// 注册监听
document.body.addEventListener('click', handler);复制代码

使用 Rx 大概的样子

Rx.Observable.fromEvent(document.body, 'click') // 注册监听.take(1) // 只取一次.subscribe(console.log);复制代码

JSbin | JSFiddle
(点击画面后会在 console 显示,记得打开 console 来看)

大致上能看得出来我们在使用 RxJS 后,不管是针对 DOM Event 还是上面列的各种 API 我们都可以透过 RxJS 的 API 来做资料操作,像是示例中用 take(n) 来设定只取一次,之后就释放内存。

说了这么多,其实就是简单一句话

在面对日益复杂的问题,我们需要一个更好的解决方法。

RxJS 基本介绍

RxJS 是一套借由 Observable sequences 来组合非同步行为事件基础程序的 Library!

可以把 RxJS 想成处理 非同步行为 的 Lodash。

这也被称为 Functional Reactive Programming,更切确地说是指 Functional Programming 及 Reactive Programming 两个编程思想的结合。

RxJS 确实是 Functional Programming 跟 Reactive Programming 的结合,但能不能称为 Functional Reactive Programming (FRP) 一直有争议。

Rx 在官网上特别指出,有时这会被称为 FRP 但这其实是个“误称”。

简单说 FRP 是操作随着时间连续性改变的数值 而 Rx 则比较像是操作随着时间发出的离散数值,这个部份读者不用分得太细,因为 FRP 的定义及解释一直存在着歧异,也有众多大神为此争论,如下

André Staltz:Rx 著名的推广者,也是 RxJS 5 主要贡献者之一,同时是 Cycle.js 的作者。Staltz 特别写了一篇文章解释为什么 Rx 不能说是 FRP 但他仍然称其为 FRP。

Juan Gomez:曾在 Netflix 工作,目前任职于 Fitbit,经常出现在国外演讨会,主要写 Android。Juan Gomez 在 Droidcon NYC 2015 的演讲中特别提出他坚持称 Rx 为 FRP。

Evan Czaplicki:任职于 NoRedInk,Elm 的作者。Evan 在 StrangeLoop 2014 的演讲中,特别为现在各种 FRP 的不同解释做分类。

笔者自己的看法是比较偏向直接称 Rx 为 FRP,原因是这较为直觉(FP + RP = FRP),也比较不会对新手造成困惑,另外就是其他各种编程范式(包含 OOP, FP)其实都是想法的集合,而非严格的指南(Guideline),我们应该更宽松的看待 FRP 而不是给他一个严格的定义。

关于 Reactive Extension (Rx)

Rx 最早是由微软开发的 LinQ 扩展出来的开源专案,之后主要由社群的工程师贡献,有多种语言支援,也被许多科技公司所采用,如 Netflix, Trello, Github, Airbnb...等。

Rx 的相关资讯

  • 开源专案 (Apache 2.0 License)
  • 多种语言支持
    • JavaScript
    • Java
    • C#
    • Python
    • Ruby
    • ...(太多了列不完)
  • 官网
  • 微软目前最成功的开源专案

LinQ 唸做 Link,全名是 Language-Integrated Query,其功能很多元也非常强大;学 RxJS 可以不用会。

Functional Reactive Programming

Functional Reactive Programming 是一种编程范式(programming paradigm),白话就是一种写程式的方法论!举个例子,像 OOP 就是一种编程范式,OOP 告诉我们要使用对象的方式来思考问题,以及撰写程式。而 Functional Reactive Programming 其实涵盖了 Reactive Programming 及 Functional Programming 两种编程思想。

Functional Programming

Functional Programming 大部分的人应该多少都有接触过,这也是 Rx 学习过程中的重点之一,我们之后会花两天的篇幅来细讲 Functional Programming。
如果要用一句话来总结 Functional Programming,那就是 用 function 来思考我们的问题,以及撰写程式

在下一篇文章会更深入的讲解 Functional Programming

Reactive Programming

很多人一谈到 Reactive Programming 就会直接联想到是在讲 RxJS,但实际上 Reactive Programming 仍是一种编程范式,在不同的场景都有机会遇到,而非只存在于 RxJS,尤雨溪(Vue 的作者)就曾在 twitter 对此表达不满!

Evan You 的推文

Reactive Programming 简单来说就是 当变数或资源发生变动时,由变数或资源自动告诉我发生变动了

这句话看似简单,其实背后隐含两件事

  • 当发生变动 => 非同步:不知道什么时候会发生变动,反正变动时要跟我说
  • 由变数自动告知我 => 我不用写通知我的每一步代码

由于最近很红的 Vue.js 底层就是用 Reactive Programming 的概念实例,让我能很好的举例,让大家理解什么是 Reactive Programming!

当我们在使用 vue 开发时,只要一有绑定的变数发生改变,相关的变数及画面也会跟着变动,而开发者不需要写这其中如何通知发生变化的每一步代码,只需要专注在发生变化时要做什么事,这就是典型的 Reactive Programming (记得必须是由变数或资源主动告知!)

Vue.js 在做 two-ways data binding 是透过 ES5 definedProperty 的 getter/setter。每当变数发生变动时,就会执行 getter/setter 从而收集有改动的变数,这也被称为依赖收集

Rx 基本上就是上述的两个观念的结合,这个部份读者在看完之后的文章,会有更深的体悟。

今日小结

今天这篇文章主要是带大家了解为什么我们需要 RxJS,以及 RxJS 的基本介绍。若读者还不太能吸收本文的内容,可以过一段时间后再回来看这篇文章会有更深的体会,或是在下方留言给我!

相关文章:

ThickBox 3.1参数详解(转)

前几天写了一篇关于ThickBox 3.1的文章:今天在使用这个东西的时候发现里面有许多参数没有详细解释,今天抽空整理出来,现和大家分享一下:先说几个参数:class"thickbox" 调用特效;height 打开页面的…

最新Java培训-NIO实战教程

Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。NIO可以理解为非阻塞IO,传统的IO的read和write只能阻塞执行,线程在读写IO期间不能干其他事情,比如调用socket.read()时&am…

获取执行SQL语句的返回结果

最近遇到的问题,在存储过程中需要拼接动态SQL语句,用变量保存,可直接使用EXECUTE SP_EXECUTESQL是不能获取想要的结果的 于是经过baidu了一番后,找到了解决的办法 declare coun int,sql nvarchar(2000)setsqlselect councount(*) …

Word文档使用密码加密

Word文档使用密码加密 方法如下: 文件-->信息-->保护文档-->用密码进行加密-->设置密码

LeetCode实战:反转链表

背景 为什么你要加入一个技术团队?如何加入 LSGO 软件技术团队?我是如何组织“算法刻意练习活动”的?为什么要求团队的学生们写技术Blog 题目英文 Reverse a singly linked list. Example: Input: 1->2->3->4->5->NULL Ou…

【UI设计培训】字体设计-偏旁部首变形

UI设计培训中字体设计也是非常重要的一节课,字体在UI设计岗位中可以说用到的频率是非常高的,是设计师必须学会并且要有娴熟运用的一项必备技能,在进行汉字设计的时候,可以把汉字拆分成几个偏旁部首的形式进行设计,这样…

【转帖】如何通过 javascript 访问 GridView/DataGrid 选中 CheckBox 行各列的值

功能需求1, 单击 checkbox 返回当前行值2, 外部按钮获取所有选择行的值实现说明参见主要代码&#xff0c;代码为自说明式。原文地址&#xff1a;http://www.cnblogs.com/Jinglecat/archive/2007/07/15/818967.html主要代码 <asp:GridView ID"GridView1" runat&q…

LeetCode实战:删除链表中的节点

背景 为什么你要加入一个技术团队&#xff1f;如何加入 LSGO 软件技术团队&#xff1f;我是如何组织“算法刻意练习活动”的&#xff1f;为什么要求团队的学生们写技术Blog 题目英文 Write a function to delete a node (except the tail) in a singly linked list, given on…

Facebook将React的许可改为MIT

Facebook决定将React原先的BSDPatents许可改为MIT&#xff0c;这样其他公司就可以将React包含在Apache基金会的项目当中&#xff0c;并消除与开源社区之间关系的不确定性。\\Facebook的一位工程主管Adam Wolff声称&#xff0c;将会有越来越多的项目使用MIT许可代替BSDPatents&a…

Java培训进阶书籍推荐,赶快收藏起来!

最近有很多学习或者已经在工作的java技术的同学都想要更进一步的提升自己&#xff0c;那么阅读书籍可以给大家带来帮助&#xff0c;今天&#xff0c;小编将分享过去几年中一些最好的Java培训进阶书籍&#xff0c;您可以在2021年阅读这些书籍&#xff0c;以更好地学习Java和相关…

LeetCode实战:二叉搜索树的最近公共祖先

背景 为什么你要加入一个技术团队&#xff1f;如何加入 LSGO 软件技术团队&#xff1f;我是如何组织“算法刻意练习活动”的&#xff1f;为什么要求团队的学生们写技术Blog 题目英文 Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given …

[转载] 杜拉拉升职记——02 单相思与性骚扰

来源&#xff1a;李可. 杜拉拉升职记(第三版). 西安: 陕西师范大学出版社, 2010, 5. 02 单相思与性骚扰的区别 拉拉注意到&#xff0c;DB所有经理办公室沿走道的这一面&#xff0c;都是用大块的玻璃来做间隔墙。 拉拉问海伦&#xff1a;“这么设计是为了美观吗&#xff1f;” …

走进云计算与虚拟化的底层核心

本文讲的是走进云计算与虚拟化的底层核心,2012年3月在国务院政府工作报告附录部分中&#xff0c;政府对云计算给出了官方的解释&#xff0c;体现了政府对云计算产业的高度重视和美好愿景。云计算在工作报告中是这样定义的&#xff1a;“云计算是基于互联网的服务的增加、使用和…

LeetCode实战:LRU缓存机制

背景 为什么你要加入一个技术团队&#xff1f;如何加入 LSGO 软件技术团队&#xff1f;我是如何组织“算法刻意练习活动”的&#xff1f;为什么要求团队的学生们写技术Blog 题目英文 Design and implement a data structure for Least Recently Used (LRU) cache. It should …

探索性测试,笔记二

测试十戒律&#xff1a; 1、你应该使用大量输入&#xff0c;来反复锤炼被测的应用程序 *大规模的随机测试&#xff08;自动化&#xff09;&#xff0c;而且有助于理解输入和输出的关系 2、你应当贪图你的邻居的应用程序 3、你应当亲自寻找睿智的预言家 *对应的输入是否有对应的…

python 监控windows磁盘空间和备份大小

#!/usr/bin/env python # Version 3.5.2 # __auth__ 无名小妖 import os import time import sendmail import psutil import collectionsdisk_used collections.OrderedDict() cur_time time.time() # current_day cur_time - cur_time % 86400 root_dir ["D:\\bac…

如何高效学习java课程

想要快速进入到java行业&#xff0c;进行系统的培训和有效的学习是非常重要的&#xff0c;那么短时间内如何高效学习java课程呢?来看看下面小编的详细介绍吧。 ​ 如何高效学习java课程? 1. 克服自身惰性&#xff0c;学习环境更佳。 参加Java培训机构学习的话&#xff0c…

2021年web前端发展方向有哪些

一年转瞬即逝&#xff0c;仅仅一年的时间&#xff0c;就能发生很多事情&#xff0c;近几年web前端行业越来越受到大家的关注&#xff0c;很多人都想看看2021年web前端发展方向有哪些?下面来看看小编详细的介绍。 2021年web前端发展方向有哪些? 1、TypeScript爆发增长 从2019年…

weblogic服务器部署的程序,如何直接通过IP访问(即URL中去掉工程名)

用weblogic部署的程序&#xff0c;怎么能够直接通过IP访问呢&#xff1f; 下面就是了 打开你的工程&#xff0c;看看webroot下的WEB-INF中有没有一个weblogic.xml文件。 1、如果没有&#xff0c;自己建一个&#xff0c;里面写上&#xff1a; <?xml version"1.0" …

LeetCode实战:二叉搜索树中第K小的元素

背景 为什么你要加入一个技术团队&#xff1f;如何加入 LSGO 软件技术团队&#xff1f;我是如何组织“算法刻意练习活动”的&#xff1f;为什么要求团队的学生们写技术Blog 题目英文 Given a binary search tree, write a function kthSmallest to find the kth smallest ele…

xml文件-1

2019独角兽企业重金招聘Python工程师标准>>> 1 Xml简单的历史介绍 1969 gml(通用标记语言) [主要的目的是要在不同的机器进行通信的数据规范] 1985 sgml(标准通用标记语言) 1993 html (www网) Html语言本身是有一些缺陷的 (1)标记不能自定义 <html> <table…

学习web前端难不难

学习web前端难不难?这是很多同学都会问到的问题&#xff0c;web前端在目前互联网行业的发展前景是非常可观的&#xff0c;想要进入到这个行业的人有很多&#xff0c;下面我们来看看具体的介绍。 学习web前端难不难?首先你要明白你需要什么 前发展还是后发展?定好系统的学习目…

Android对话框-下篇-之设置activity为Dialog

有人希望做出来的应用程序是一个漂浮在手机主界面的东西&#xff0c;那么很 简单你只需要设置一下Activity的主题就可以了在AndroidManifest.xml 中定义Activity的 地方一句话&#xff1a;android:theme"android:style/Theme.Dialog" 这就使你的应用程序变成对话框的…

Codeforces 846 B Math Show DFS + 贪心

题目链接&#xff1a; http://codeforces.com/contest/846/problem/B 题目描述&#xff1a; 有N个节点&#xff0c; 每个节点有相同的K个子节点&#xff0c; 每个子节点有时间花费&#xff0c;完成一个子节点获得1分&#xff0c; 每完成一个节点的所有子节点获得额外一分&…

LeetCode实战:二叉树的最近公共祖先

背景 为什么你要加入一个技术团队&#xff1f;如何加入 LSGO 软件技术团队&#xff1f;我是如何组织“算法刻意练习活动”的&#xff1f;为什么要求团队的学生们写技术Blog 题目英文 Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the …

学习UI设计都需要了解哪些知识

由于UI设计的高薪&#xff0c;很多人都萌生了想要学习UI设计的想法&#xff0c;但是小编提醒大家&#xff0c;学习UI设计之前一定要做足功课&#xff0c;了解UI设计基本知识&#xff0c;再看看自己是否适合学习&#xff0c;下面小编就为大家详细的介绍一下学习UI设计都需要了解…

Marty Cagan:怎样寻找出色的产品经理

《程序员杂志》的文章&#xff0c;原帖位于http://www.programmer.com.cn/7760/ 写的很好&#xff0c;自己转贴存储一下&#xff0c;也符合Product Owner的要求&#xff0c;就是……要求太高了&#xff01;本文是他回顾自己二十多年来从事软件产品管理工作的总结和经验分享&…

LeetCode实战:除自身以外数组的乘积

背景 为什么你要加入一个技术团队&#xff1f;如何加入 LSGO 软件技术团队&#xff1f;我是如何组织“算法刻意练习活动”的&#xff1f;为什么要求团队的学生们写技术Blog 题目英文 Given an array nums of n integers where n > 1, return an array output such that ou…

PHP+MySql获取自动增长字段的新添加记录ID值

PHPMySql获取新添加记录的ID值 1.假设字段名称为recordID 2.字段属性须设为&#xff1a;auto_increment 3.添加数据后使用 $newID mysql_insert_id(); 得到ID值 ASP获取即时ID值 ASPAccess2000 1.要获取的ID值字段属性必须设为&#xff1a;自动编号(我们假设字段名为recordID)…

MyBatis框架添加客户有哪些步骤

在MyBatis的映射文件中&#xff0c;添加操作是通过元素来实现的。例如&#xff0c;向数据库中的t_customer表中插入一条数据可以通过如下配置来实现。 在上述配置代码中&#xff0c;传入的参数是一个Customer类型&#xff0c;该类型的参数对象被传递到语句中时&#xff0c;#{us…