承诺与可观察与流

受与我的一位同事的讨论的启发,该同事想知道Observable和promise是否是同一回事,所以我决定写这个博客来解释它们之间的区别。

Promises和Observables都可以帮助我们使用JavaScript中的异步功能 。 承诺是将以异步方式(如http调用)解析的值。 当异步操作完成或失败时,它们将处理单个事件

可观察对象就像Promises,不同之处在于它们使用多个值,它们自己清除后可以取消。 如果不再需要HTTP请求或某些异步操作的结果,则Observable的Subscription可以取消订阅,而Promise最终将调用成功或失败的回调,即使您不需要该通知或结果提供了。

一个Observable就像一个Stream(在许多语言中),并允许传递0、1或更多事件,其中每个事件都调用回调。 它们处理一系列异步事件

可观察对象提供Promise等功能:

  • 它们会随着时间的推移具有多个值:如果我们保持对新闻简报的订阅开放,我们将不时获得一个新的订阅。 发件人决定何时获取它,但我们必须等到它来临。
  • 他们有多个管道
  • 它们支持聚合操作,例如map,filter,forEach,reduce,…
  • 我们可以执行一些强大的功能,例如使用zipmergeconcat将不同的Observable组合到一个新的Observable

由于Observables用于处理“异步事件序列”的反应式编程中,因此让我们看一下Uladzimir Sinkevich的实际示例,这意味着什么:

假设是星期五,约翰想在今天晚上和他的朋友鲍勃一起度过,披萨披萨,观看《星球大战》的一集。 让我们概述一下他的选择。

  1. 约翰完成了他的工作。 然后去订购披萨,等到完成为止。 然后接他的朋友。 最后(与鲍勃和披萨一起)回到家看电影。 这将是同步方法,而且时间太长,以至于John可能想在那个时候取消它。
  2. 约翰在网上订购了他的披萨,给鲍勃打电话,邀请他来。 他回家,送了披萨,开始看电影(和吃披萨),而不必等鲍勃露面。 这就是异步方法可能发生的情况。
  3. John订购披萨,给Bob打电话,邀请他来,回家,然后送披萨。 但是这次,他等到鲍勃(Bob)来,然后才打开电影。 这就是反应性方法的目的。 您要等到所有异步操作(更改)完成后再继续执行其他操作。

“反应式编程是使用异步数据流进行编程。” Andre Staltz

在这个阶段,在看到我们可以使用Observable做什么之后,我的同事问了下一个好的问题:
“由于它们具有相似的运算符,我们是否可以像处理Java流一样处理Observable(在前端)?”

可观察和流看起来非常相似。 它们具有相似的运算符(过滤器,地图等),但是Observable与Streams明显不同:

  • 流只是随时间到达的集合。
  • 可观察对象就像集合……只是它们随着时间的推移异步到达。
  • 流只能使用一次,Observable可以订阅很多次。
  • 流是基于拉的 :数据消费者决定何时从数据生产者那里获取数据。 生产者不知道何时将数据传递给消费者。 这仅适用于同步事物。 要从集合中提取值,必须立即可用 如果我们将同步视为“推”,那么我们可以将异步视为“推”。
  • Observable是基于推送的 :数据生产者(新闻通讯的创建者)决定消费者(新闻通讯的订户获取数据)的时间。 承诺是最常用的Java 推送方式。 一个promise(生产者)将一个解析的值传递给已注册的回调(消费者),但是与函数不同的是,promise负责精确确定何时将该值送到回调中。

每个Javascript函数都使用pull; 该函数是数据的产生者,并且调用该函数的代码通过从其调用中提取单个返回值来使用它。

一个Observable是多个值的生成它们给订阅者。 我们订阅了一个Observable,当下一项到达onNext或流完成onCompleted或发生错误onError时,我们将得到 通知 。 因为使用Observable我们会收到onNextonCompletedonError事件。 我们可以做的其他事情是缓存,限制……

Java 8 Streams API与RxJava

让我们以来自Java 8 Streams API的Streams(java.util.stream)和来自RxJava的Observables(用于Java的ReactiveX API,用于可观察流的异步编程)为例。 这两个API并非为相同的用途而构建。

  • 我们可以使用RxJava 执行 asynchonus 任务
  • 使用Java 8流,我们将遍历您的collection的项目
  • 我们可以在RxJava(集合中的遍历项)中执行几乎相同的操作,但是,由于RxJava专注于并发任务,…,它使用同步,闩锁,……因此,使用RxJava的同一任务可能会比Java 8流慢。 。
  • 可以将RxJava与CompletableFuture进行比较,但是它可以计算多个值。
  • 默认情况下,RxJava是单线程的。 除非我们开始使用Scheduler,否则所有事情都会在同一线程上发生。

最后一件事:流与收藏

您已经注意到,我们故事中的第四位参与者是: Collection 。 Java 8 Streams API提供了一种与Java集合一起使用的机制。 这是关于将集合转换为流, 并行处理元素,然后将结果元素收集到集合中。

  • 集合是内存中的数据结构,其中包含元素。 集合中的每个元素都是在它实际上成为该集合的一部分之前进行计算的。 因此,它是一组急切计算的值。
  • 流是固定的数据结构,可按需计算元素。 Java 8 Streams可以看作是延迟构造的Collections,其中,当用户需要时可以计算值。
  • 与功能性编程语言一样,流支持聚合操作,这些操作可以串行或并行执行:过滤,映射,缩小,查找,匹配,排序,限制,收集等。
  • 流还支持管道和内部迭代:大多数Java 8流操作仅返回流。 这有助于我们创建各种流操作的链→这称为流水线。 流水线操作看起来类似于SQL查询。

今天就这样!

我希望您能加深对承诺,可观察和顺畅的理解,并且下次您遇到这些术语时,它们不会使您感到困惑或困惑。