Rx 处理器目录 (Catalog of Rx operators)
目标 | 可选方式 | Rx 处理器(Operator) |
---|---|---|
创建 Observable Creating Observables | 直接创建 By explicit logic | Create Defer |
根据范围创建 By specification | Range Repeat Generate Timer Interval Return | |
使用预设 Predefined primitives | Throw Never Empty | |
从其他类型创建 From other types | FromEventPattern FromEvent FromTask FromAsync | |
变换 Transforming | 单一值 To single value | Select Materialize/Dematerialize Timestamp TimeInterval |
展开内部的Collection 或者Observable Flattening inner collections/observables | SelectMany | |
分割成子序列 Splitting to subsequences | 根据顺序或者时间 By coincidence/time | Buffer Window |
根据分组条件 By common key | GroupBy GroupByUntil | |
控制 Observer 和Observable 之间的关系 Controlling the observer- observable relationship | 从观察者角度进行控制 The observed sequence | Take TakeUntil TakeWhile Skip SkipWhile SkipUntil StartWith |
从订阅者角度进行控制 The subscription | Publish/PublishLast Multicast Replay RefCount Subscribe/DelaySubscription | |
组合 Combining | 多值组合 Values from multiple | CombineLatest WithLatestFrom Zip Merge GroupJoin |
每次取一个值 Values from one at a time | Concat Switch Join Amb |
前言
本书名为《Rx.NET 实战》(Rx.NET in Action),本书很好地介绍了,在.NET 开发人员使用 Rx时,需要的细节和基础知识。特别是,它解释了如何将 .NET 中的大量异步类型连接到 Rx Observable(可观察序列),以及如何处理错误、资源分配和并发性问题。
自问世以来,.NET Framework 一直强调异步执行和非阻塞 I/O 的重要性。通过委托,.NET Framework 从一开始就强调了高阶函数式编程。通过在委托上自动定义 BeginInvoke 和 EndInvoke 方法,开发人员可以异步调用任何方法。
但是,异步操作的 BeginInvoke/EndInvoke 模式既繁琐又冗长,因为它需要将代码转换为**延续传递(continuation-passing)**的模式。作为替代方案,.NET Framework 引入了基于事件的异步模式,该模式使用 .NET 对事件和事件处理程序的内置支持。与异步委托相比,虽然基于事件的模式向前迈进了一大步,但仍有更多的方式可以简化开发。
在处理同步数据流这个问题上,利用 Enumerable/IEnumerator 接口,LINQ 标准查询处理器(Operator)可以将该问题转换成声明式的方法进行处理,漂亮且优雅。如果我们能将事件也理解成数据流,并为事件提供一个类似 LINQ 的编程模型,岂不美哉?
当把事件用于异步调用时,我们会发现一个问题或者说是弊端,那就是大多数事件(例如鼠标点击事件)与异步操作绑定过程中,最多只能产生一个值。如果我们能利用这一规律——即异步方法只返回一个值,然后给异步方法构建一个类似命令式编程的模型,并支持常规的类似控制流的条件、循环和异常处理,岂不更好?
事实证明,这两个问题的答案都是肯定的! 通过使用均衡化的数学技巧,我们可以将 同步拉式流(synchronous pull-based stream) 中的 IEnumerable /IEnumerator 接口,转换成 异步推式流(asynchronous push-based stream) 中的 IObservable /IObserver 接口。 C# 和 Visual Basic 中的 async/await 语法允许开发人员使用常规命令语法编写同步和异步方法,而 LINQ 完全有能力支持发人员编写同步和异步,两种数据流的查询。
这就是 Rx 的核心。现在,.NET 之外的许多语言都采用了 one/many混合sync/async 的模式,这使得开发人员无论使用哪种语言都能愉快地工作。
如果你是一名.NET开发人员,你一定要随身携带本书,以便将 Rx.NET 用于实践!
— 埃里克-梅耶 ERIK MEIJER
RX 的发明者,应用对偶(APPLIED DUALITY)的创始人
阅读笔记:作者是applied duality的创始人,这个叫做applied duality公司的主页上有张图很有意思。
x轴黄色代表数据速率变化的大小,应该是说数据从静态拉取(pull)变化成动态推送(push);
y轴蓝色表示多样化的变化,应该是描述数据的表达方式从外键/主键模式(fk/pk)变化到主键/值模式(key/value);
z轴红色代表体量的变化,这个好理解,就是从小数据量(small)到大数据量(big);
这张图我觉得作者想表达两层含义:
- 作者认为Rx技术,从某种层面上可以理解为一种改良的sql技术,Rx可以适应数据的速率变化x,多样化y,体量变化z。
- 作者认为Rx声明式编程和Sql声明式编程之间存在对等性,彼此在处理数据的思想上是互通的。
从主页的介绍中能看到,作者发现时代在变化,数据逐渐从原来的静态模式转换成动态模式。他应该是想让Rx技术能像Sql一样,以一种声明的方式让人们去处理数据。毕竟用过Sql的人都能感受到她特殊的魅力。
序言
Reactive Extensions (Rx) for .NET 于 2009 年 11 月首次发布,其简短描述为:"Rx 是一个 .NET 库,允许程序员编写简洁的声明式代码,根据熟悉的 .NET 习惯和模式,来协调异步和基于事件的程序。(见 http://mng.bz/gQ31)。
我还记得我当时观看了第一个示例,并阅读了讨论内容。这解决方案如此优雅和简单,让我惊叹不已。不幸的是,当我亲自尝试使用 Rx 时,发现事情比我想象的要难得多,在反应式编程方式上,我需要重新改变我的思维模式。在那个年代,这方面的资料并不多,我不得不努力解决自己的问题,并通过大量的试错来艰难地学习。
2012 年,在我服兵役结束并加入 CodeValue(www.codevalue.net)之后,有两个重大项目让我真正体会到了Rx的优势。第一个项目是一个网络安全应用程序,它需要对多个事件做出反应并进行协调,以便向最终用户显示并发的各种事件的状态。第二个是在移动和 PC 设备上运行视频聊天APP。视频聊天APP对用户登录和退出系统等事件做出反应,且必须以不同方式,接收处理各类信息。尽管这两个系统并不相同,但它们却面临同一个问题,即根据事件编写流程。该流程涉及对接收值过滤,处理异步和并发,以及识别重复发生的事件模式,以便应用程序能够高效、正确地做出响应。 我在这两个系统中都引入了 Rx,这也是每个系统取得成功的原因之一。我们的工作超出了预期,也比计划提前完成。
不过,尽管我掌握了 Rx 方面的知识,问题还是时有发生,而有关 Rx 的书籍和指南等资料却很少。很多时候,问题的起因是我的同事们缺乏相关知识,或者出现了对我们来说很陌生的情况。幸运的是,在我找到问题根源后,问题很容易就解决了,这主要是因为 Rx 处理器的灵活性。在接下来的几年里,我开始在博客上谈论 Rx 以及它如何让复杂问题的解决变得简单。就在那时,我萌生了写这本书的想法。 我的愿景是编写一本循序渐进的指南,希望让.NET程序员尽可能获取到使用Rx库和反应式编程所需的内容。我还想在书中介绍我多年来获得的实践经验,以及存在的问题和解决办法。
为了确保本书实现其目标,我付出了艰苦而细致的工作。有些章节必须重写,有些主题必须更改,有些材料必须删去,以便集中介绍重要的基本功能。这些辛勤工作的成果就是《Rx.NET in Action》,这是一本可以从头到尾阅读的书,也可以直接翻阅特定章节来解决问题或加深记忆。
Rx 是一种不断发展的技术,也被移植到了许多其他平台和语言上。它是一个开源项目,是 .NET 基金会(www.dotnetfoundation.org)的一部分。我希望 Rx 将成为在 .NET 中编程、组织和协调异步和基于事件的程序的实际方法,并希望本书能为你提供所需的一切,让你为 Rx 这个令人兴奋的新世界做好准备。
阅读感悟:感谢作者对于Rx的贡献,每每读到前言,我也是感慨万千,作为一个程序员能找到的Rx中文资料少之又少。境遇和作者写书时其实是一样的,希望本书能给更多人带来惊喜和快乐。
致谢
谨以此书献给我的妻子加芙列拉。 在我写作的整个过程中,是你的支持、关爱和照顾让我得以将这本书变成现实。我爱你,我钦佩你在我忙于写作时所付出的许多努力。
我美丽的孩子希拉和约纳坦,你们给我的生活带来了欢乐和光明;我深爱着你们。当你们睡着时,坐在你们身边,给了我许多章节的灵感。
感谢我的父母埃斯特和什洛莫,是他们给我买了第一台电脑,点燃了我对计算机科学的热情。
感谢我的表弟盖伊,他对我的生活和我今天看待事物的方式产生了巨大影响,我的许多软件能力都源于你的教导。
我的其他家人在我和他们聊天时,不得不忍受我的思绪飘到书上,我感谢你们所做的一切。
特别要感谢我的好朋友 Dror Helper,他在我不知情的情况下给了我很多建议,这些建议促成了这本书的诞生。
还要感谢我在 CodeValue 的所有同事,他们在整个过程中给予了我大力支持。
特别感谢 Erik Meijer 为我的书提供了精彩的前言,当然也要感谢他帮助创建了 Rx。
感谢 Manning 的员工。在编辑、制作和推广方面与我一起工作的每个人,无论是直接的还是幕后的,都帮助我创作出了最好的图书。这确实是一个团队的努力。
感谢在写作和发展过程中提供反馈意见的众多审稿人: Bruno Sonnino、Bachir Chihani、Carsten Jørgensen、Dror Helper、Edgar Knapp、Fabrizio Cucci、Goetz Heller、Ignacio Rigoni、Jason Hales、Joel Kotarski、Jorge Branco、Mattias Lundell、Michele Mauro、Oscar Vargas、Rohit Sharma 和 Stephen Byrne。还要感谢技术校对员科迪-桑德(Cody Sand),他一丝不苟地审阅了最终稿件的示例代码。
最后,非常感谢 Rx 团队和贡献者们,是他们打造了一项出色的技术。
关于本书
《Rx.NET in Action》是一本面向 .NET 开发人员的反应式扩展库完整指南。书中提供了解释、最佳实践、技巧和窍门,使你能够在应用程序中充分使用 Rx。
谁应该阅读本书?
Rx.NET in Action 适用于编写基于事件和异步应用程序的.NET 开发人员,他们需要对事件和基于推送的源进行强大的消费和查询功能。
《Rx.NET in Action》也适合那些对反应式程序设计和 Rx 库技术感到好奇,但又不急需使用的开发人员。在你的工具箱中添加 Rx 知识对未来的项目很有价值;反应式编程是一个热门话题,在未来仍将如此。
本书主要使用 Rx 的 .NET 版本,代码示例使用 C# 语言。熟悉 C# 的读者可以轻松掌握。
本书适用于 .NET 支持的任何平台(包括 .NET Core)。
本书的编排方式
全书共 11 章,分为两个部分。
第 1 部分,介绍了反应式编程以及理解库的功能方面所需的 .NET 技能。
- 第 1 章探讨了反应式编程范式和反应式宣言概念。该章介绍了 Rx 的构建模块,并解释了何时以及为何要使用 Rx。
- 第 2 章是你真正接触 Rx 的地方,也是将 Rx 融入你的应用程序所需的步骤。它展示了在应用程序中使用 Rx 的简单案例研究,并比较了同一应用程序在使用 Rx 之前和之后的两个版本。
- 第 3 章概述了 Rx 使用的函数式编程概念和技术,以及它们如何与 .NET 框架和 C# 语言结合使用。
第 2 部分,深入介绍了使用 Rx 所要完成的每项任务——从创建Observable
(可观察序列)和Observer
(观察者)对象,到控制它们的生命周期以及对在它们之上创建的查询做出反应。
- 第 4 章介绍了创建
Observable
(可观察序列)的方法,并展示了如何通过枚举式和内置创建Operator(处理器)创建同步Observable
(可观察序列)。 - 第 5 章解释了 Rx 处理异步代码的方式,以及如何将本地 .NET 异步类型桥接到可观察对象中。本章还讨论了异步代码在现代应用程序中的重要性,以及如何在程序中添加周期性行为。
- 第 6 章集中讨论了
Observable
(可观察序列) 与observer
(观察者) 的关系以及如何控制这种关系。在这一章中,我讲解了针对各种场景创建observer
(观察者)的最佳方法,以及如何限制observer
(观察者)订阅的生命周期。 - 第 7 章解释了热观察对象和冷观察对象的区别,并介绍了 Rx subject。 本章教你如何在
observer
(观察者)订阅观察对象时控制Observable
(可观察序列) 的状态,以及如何在observer
(观察者)之间共享排放。 - 第 8 章提供了 Rx 库中提供的基本查询处理器(Operator)目录。Rx 通常被称为 LINQ to Events,了解 Rx 处理器(Operator)的详细信息将有助于你构建功能强大的查询,从而节省你的时间和精力。
- 第 9 章延续了第 8 章的内容,展示了分割和组合
Observable
(可观察序列)的高级方法。你将学习如何根据条件或巧合对元素进行分组,以及如何对observer
(观察者)之间的相关性做出反应。 - 第 10 章深入探讨了 Rx 并发模型和同步。我介绍了Scheduler(调度器)的概念,并解释了 Rx 提供的Scheduler(调度器)。 然后,我将讲解如何控制 Rx 查询的时间和计算位置。
- 第 11 章教你保护 Rx 查询免受故障影响,并对查询处理中可能发生的错误做出反应。本章还介绍了管理由 Observable(可观察序列)和 Rx 查询消耗的资源的方法。
本书还有三个附录:
- 附录 A 总结了 .NET 中异步编程的概念。
- 附录 B 介绍了 Rx Disposables 库,并解释了如何使用该库提供的实用程序。
- 附录 C 解释了如何测试 Rx 处理器(Operator)和查询。
本书可作为指南和参考书使用。如果你是 Rx 的新手,我建议你从头开始阅读。如果你已经熟悉了 Rx 概念,根据你要完成的任务阅读特定章节可能会有所帮助。
关于代码
本书包含许多源代码示例,既有编号列表,也有与普通文本并列的示例。 在这两种情况下,源代码的格式都是固定宽度的字体,以便与普通文本区分开来。有时,代码也以粗体显示,以突出显示与本章前几步相比发生变化的代码,例如,当新功能添加到现有代码行时。
在许多情况下,原始源代码都经过了重新格式化;我们添加了换行符,并重新调整了缩进,以适应书中可用的页面空间。在极少数情况下,即使这样做也是不够的,因此在列表中加入了换行标记(➥)。此外,源代码中的注释往往在正文描述代码时从列表中删除。许多列表都附有代码注释,以突出重要概念。
本书的源代码可从出版商的网站(www.manning.com/books/rx-dot-net-in-action) 和GitHub(https://github.com/tamirdresher/RxInAction) 下载。该代码的使用说明包含在资源库根目录下的 README 文件中。
在电子书中,某些列表和代码片段使用了颜色。蓝色用于表示原始类型和保存的关键字。 水蓝色用于突出显示用户定义的类型,红色用于字符串字面量。棕色用于字符串参数占位符,绿色用于注释。一如既往,黑色为用户代码。
作者在线
购买《Rx.NET in Action》后,你可以免费访问由 Manning Publications 管理的私人网络论坛,在这里你可以对本书发表评论,提出技术问题,并从作者和其他用户那里获得帮助。要访问论坛并订阅,请将浏览http://www.manning.com/books/rx-dot-net-in-action。本页提供的信息包括注册后如何进入论坛、可获得的帮助种类以及论坛行为规则。
Manning对读者的承诺是提供一个场所,让读者个人之间以及读者与作者之间能够进行有意义的对话。这并不是对作者参与的具体数量的承诺,作者对作者在线论坛的贡献仍然是自愿的(而且是无偿的)。我们建议你试着向作者提出一些具有挑战性的问题,以免他对这本书产生兴趣。
对本书的兴趣
题外话!只要本书还在印刷,就可以从出版商的网站上访问作者在线论坛和以前的讨论档案。其他在线资源
如果你对 Rx 感兴趣,还可以访问 Rx 门户网站 http://reactivex.io,它提供了一个开发者中心。其中包含有关该库及其端口的
最新信息
Rx.NET 是一个开源项目,你可以在 https://github.com/dotnet/reactive上找到完整的代码和讨论。
如果你想咨询有关 Rx 的问题,可以访问 gitter 频道(https://gitter.im/Reactive-Extensions/Rx.NET) 或slack的#rx 频道,这需要你通过 .NET Core Slack 频道的注册页面(http://tattoocoder.com/aspnet-slack-sign-up/) 进行订阅。
关于作者
TAMIR DRESHER 是一名高级软件架构师,在以色列的 CodeValue 公司担任顾问。作为微软编程社区的杰出成员,Tamir 经常在开发者会议上就软件开发主题发表演讲,并在 Ruppin 学术中心担任软件工程讲师。
作为 .NET Framework 和软件工艺方面的专家,Tamir 已经培训了数百名开发人员,并为商业和公共部门的许多知名客户提供了帮助。
自 Rx 发布以来,Tamir 一直在使用它,且爱不释手。作为早期使用者之一,Tamir 了解 Rx 库的内部结构,并积极地向其他开发人员介绍 Rx,帮助他们利用反应式编程的强大功能提高编程技能。
Tamir 在他的博客 www.tamirdresher.com 上讲述了他的编程经历。
关于封面插图
《Rx.NET in Action》封面上的人物标题为 “中国僧侣或道士的习惯”。插图选自出版商托马斯-杰弗里斯(Thomas Jefferys)的《古今各国服饰集》(四卷)伦敦,1757 年至 1772 年间出版。扉页上标明这些是手工上色的铜版雕刻,并用阿拉伯树胶增色。 托马斯-杰弗里斯(1719-1771 年)被称为 “乔治三世的地理学家”。作为一名英国制图师,他是当时领先的地图供应商。他为政府和其他官方机构雕刻和印刷地图,并制作了大量商业地图和地图集,尤其是北美地图。作为一名地图绘制者,他对所勘测地当地的服饰和风土人情产生了浓厚的兴趣,他将这些都收藏在书中,内容十分精彩。
在 18 世纪晚期,以休闲为目的的出国旅行度假相对较少,于是乎像这样的作品集便很受欢迎,它向游客和人们介绍了其他国家的居民。 杰弗里斯画册中图画丰富多彩,生动地展现了约 200 年前世界各国的异域风情。自那以后,着装发生了变化,像当时那样,如此丰富的地区性也逐渐消失。 现在,人们常常很难分辨出一个大洲和另一个大洲的居民。 也许,乐观地看,我们用文化和视觉的多样性换来了更加丰富多彩的个人生活。或者说,我们换来了更丰富多彩、更有趣的知识和技术生活。
在我们很难区分一本电脑书籍和另一本书籍的时候,Manning 用杰弗里斯的图片还原了两个世纪前丰富多彩的地区生活,用书籍封面颂扬了电脑行业的创造力和主动性。