Observables (Rx.js) 与 ES2015 生成器相比如何?
How does Observables (Rx.js) compare to ES2015 generators?
据我了解,解决异步编程工作流的技巧如下:
- 回调(CSP)
- 承诺
新方法:
- Rx.js Observables(或 mostjs,bacon.js,xstream 等)
- ES6 生成器
- Async/Await
我们现在正在从回调和承诺转向这些更新的方法。我目前的理解是 - Async/Await 更像是在 ES2015 生成器之上的更清晰的抽象。
我无法理解的是 Observables 和 Generators 之间的概念差异。我已经广泛使用它们并且使用它们没有问题。
让我感到困惑的是 Observables 和 Generators 的用例。我得出的结论是,他们最终解决的是同一个问题——异步性。我看到的唯一潜在区别是生成器天生就为代码提供了命令式语义,而使用 Rxjs 的 Observable 似乎提供了反应式范例。但就是这样吗?
这应该是在 Observable 和 Generator 之间进行选择的标准吗?有什么优缺点。
我是不是错过了大局?
随着 Observable 最终成为未来的 Ecmascript,Promises(带有可取消令牌)/Observable/Generators 是否会相互竞争?
Observables 推动变化,因此是 observable,而不是响应它的函数,是在控制之中。另一方面,生成器需要您从中提取值。因此,将对新值做出反应的函数决定了它何时准备好接受新值。
我在使用 observables 的背压方面遇到了麻烦,但是对于生成器,你可以随心所欲地释放值。
编辑:最后一个问题。 Promises 只是仅发出一次的可观察对象,所以我认为它们不会相互竞争。我认为真正的战斗将是 async/await 与 observables,并且 async/await 已经领先,并且已经在 C# 中(现在 Node.js)。但是 Observables 有那种甜美的 FRP 感觉,而函数式编程非常酷,所以我认为它们最终都会得到很大的关注。
Edit2:André Staltz,Cycle.js 和 xstream 的作者,Rx.js 的贡献者,写了一篇关于生成器如何工作的很棒的文章和 Observables 相关(2018-01-31)。特别是,他展示了它们如何从共同基础 class.
继承而来
And now a consumer can be a Listener (“observer”) or a Puller, it’s up to the consumer whether it will pull the producer or not. And the producer can be a Listenable (“observable”) or a Pullable (“iterable”), it’s up to the producer whether it sends data proactively or only on demand. As you can see, both consumer and producer are simple functions of the same type:
(num, payload) => void
So any operator that we build will work for both reactive programming or iterable programming, simply because the line between those two modes gets blurred and it’s not anymore about observables versus iterables, it’s just about transformations of data between producer and consumer.
我建议阅读它 [link]. The article introduces "Callbags", a spec for callbacks used for reactive and iterable programming. He implements that spec to make a tiny library 以了解可迭代和反应式编程。为了吸引您阅读这篇文章并查看库,这里有一些基于他介绍的规范的 7kb 库中的示例:
响应式编程示例
从每秒滴答作响的时钟中选出前 5 个奇数,然后开始观察它们:
const {forEach, interval, map, filter, take, pipe} = require('callbag-basics');
pipe(
interval(1000),
map(x => x + 1),
filter(x => x % 2),
take(5),
forEach(x => console.log(x))
);
// 1
// 3
// 5
// 7
// 9
可迭代编程示例
从一系列数字中,选出 5 个并除以 4,然后开始一个一个地提取:
const {forEach, fromIter, take, map, pipe} = require('callbag-basics');
function* range(from, to) {
let i = from;
while (i <= to) {
yield i;
i++;
}
}
pipe(
fromIter(range(40, 99)), // 40, 41, 42, 43, 44, 45, 46, ...
take(5), // 40, 41, 42, 43, 44
map(x => x / 4), // 10, 10.25, 10.5, 10.75, 11
forEach(x => console.log(x))
);
// 10
// 10.25
// 10.5
// 10.75
// 11
您可以将 rxjs 可观察对象视为异步生成器,即生成承诺的生成器。仅仅因为内容不能保证在我们调用 .next 时就绪(与常规生成器相反)
- 订阅者将永久消费生成器的内容(调用.next)
- 等待 returned 承诺得到解决(或撤销)以执行您想要的操作
- Observable(使用异步生成器制作)将在生成器 return 上完成。
我知道这个问题是在 2016 年发布的,其中 generator
仍然被同步使用。
不过,我觉得今天一个更有趣(合适)的问题是async generator
和reactive observable
或reactive programming
之间的区别。请允许我跑题。
在下文中,我将使用:
A
表示async/await, promise
等
B
表示async generator
C
表示reactive observable
.
首先,它们都是为处理async
数据而设计的。重要的是细节。
如果我们有一个有限且小的 async
数据源,例如单个 HTTP 请求,磁盘上有几 KB 的数据。那么A
胜出,简单明了
当数据源变得无限(例如用户点击)或太大而无法保存在内存中时,A
将无法正常工作,因为我们会很快 运行 进入偶然的复杂性(处理以背压开始)。 B
和 C
总体上都很出色,因为它们都以某种方式提供背压功能。
然后,当数据源开始需要缓冲、去重、去抖动、merging/interleaving与其他数据源等时,C
wins as many library 将提供通用运算符来帮助处理常见的流问题。一个示例用例是阻止用户在短时间内发送垃圾评论 window(例如 5s)。
这是否意味着 C
通常比 B
好?
在我看来,没有。尽管 C
更通用,但 B
更简单、更灵活,并且与语言的集成更好(例如 for await ... of
)。而且它几乎不需要您按照 C
的要求更改整个编程范例。
据我了解,解决异步编程工作流的技巧如下:
- 回调(CSP)
- 承诺
新方法:
- Rx.js Observables(或 mostjs,bacon.js,xstream 等)
- ES6 生成器
- Async/Await
我们现在正在从回调和承诺转向这些更新的方法。我目前的理解是 - Async/Await 更像是在 ES2015 生成器之上的更清晰的抽象。
我无法理解的是 Observables 和 Generators 之间的概念差异。我已经广泛使用它们并且使用它们没有问题。
让我感到困惑的是 Observables 和 Generators 的用例。我得出的结论是,他们最终解决的是同一个问题——异步性。我看到的唯一潜在区别是生成器天生就为代码提供了命令式语义,而使用 Rxjs 的 Observable 似乎提供了反应式范例。但就是这样吗?
这应该是在 Observable 和 Generator 之间进行选择的标准吗?有什么优缺点。
我是不是错过了大局?
随着 Observable 最终成为未来的 Ecmascript,Promises(带有可取消令牌)/Observable/Generators 是否会相互竞争?
Observables 推动变化,因此是 observable,而不是响应它的函数,是在控制之中。另一方面,生成器需要您从中提取值。因此,将对新值做出反应的函数决定了它何时准备好接受新值。
我在使用 observables 的背压方面遇到了麻烦,但是对于生成器,你可以随心所欲地释放值。
编辑:最后一个问题。 Promises 只是仅发出一次的可观察对象,所以我认为它们不会相互竞争。我认为真正的战斗将是 async/await 与 observables,并且 async/await 已经领先,并且已经在 C# 中(现在 Node.js)。但是 Observables 有那种甜美的 FRP 感觉,而函数式编程非常酷,所以我认为它们最终都会得到很大的关注。
Edit2:André Staltz,Cycle.js 和 xstream 的作者,Rx.js 的贡献者,写了一篇关于生成器如何工作的很棒的文章和 Observables 相关(2018-01-31)。特别是,他展示了它们如何从共同基础 class.
继承而来And now a consumer can be a Listener (“observer”) or a Puller, it’s up to the consumer whether it will pull the producer or not. And the producer can be a Listenable (“observable”) or a Pullable (“iterable”), it’s up to the producer whether it sends data proactively or only on demand. As you can see, both consumer and producer are simple functions of the same type:
(num, payload) => void
So any operator that we build will work for both reactive programming or iterable programming, simply because the line between those two modes gets blurred and it’s not anymore about observables versus iterables, it’s just about transformations of data between producer and consumer.
我建议阅读它 [link]. The article introduces "Callbags", a spec for callbacks used for reactive and iterable programming. He implements that spec to make a tiny library 以了解可迭代和反应式编程。为了吸引您阅读这篇文章并查看库,这里有一些基于他介绍的规范的 7kb 库中的示例:
响应式编程示例
从每秒滴答作响的时钟中选出前 5 个奇数,然后开始观察它们:
const {forEach, interval, map, filter, take, pipe} = require('callbag-basics');
pipe(
interval(1000),
map(x => x + 1),
filter(x => x % 2),
take(5),
forEach(x => console.log(x))
);
// 1
// 3
// 5
// 7
// 9
可迭代编程示例
从一系列数字中,选出 5 个并除以 4,然后开始一个一个地提取:
const {forEach, fromIter, take, map, pipe} = require('callbag-basics');
function* range(from, to) {
let i = from;
while (i <= to) {
yield i;
i++;
}
}
pipe(
fromIter(range(40, 99)), // 40, 41, 42, 43, 44, 45, 46, ...
take(5), // 40, 41, 42, 43, 44
map(x => x / 4), // 10, 10.25, 10.5, 10.75, 11
forEach(x => console.log(x))
);
// 10
// 10.25
// 10.5
// 10.75
// 11
您可以将 rxjs 可观察对象视为异步生成器,即生成承诺的生成器。仅仅因为内容不能保证在我们调用 .next 时就绪(与常规生成器相反)
- 订阅者将永久消费生成器的内容(调用.next)
- 等待 returned 承诺得到解决(或撤销)以执行您想要的操作
- Observable(使用异步生成器制作)将在生成器 return 上完成。
我知道这个问题是在 2016 年发布的,其中 generator
仍然被同步使用。
不过,我觉得今天一个更有趣(合适)的问题是async generator
和reactive observable
或reactive programming
之间的区别。请允许我跑题。
在下文中,我将使用:
A
表示async/await, promise
等B
表示async generator
C
表示reactive observable
.
首先,它们都是为处理async
数据而设计的。重要的是细节。
如果我们有一个有限且小的 async
数据源,例如单个 HTTP 请求,磁盘上有几 KB 的数据。那么A
胜出,简单明了
当数据源变得无限(例如用户点击)或太大而无法保存在内存中时,A
将无法正常工作,因为我们会很快 运行 进入偶然的复杂性(处理以背压开始)。 B
和 C
总体上都很出色,因为它们都以某种方式提供背压功能。
然后,当数据源开始需要缓冲、去重、去抖动、merging/interleaving与其他数据源等时,C
wins as many library 将提供通用运算符来帮助处理常见的流问题。一个示例用例是阻止用户在短时间内发送垃圾评论 window(例如 5s)。
这是否意味着 C
通常比 B
好?
在我看来,没有。尽管 C
更通用,但 B
更简单、更灵活,并且与语言的集成更好(例如 for await ... of
)。而且它几乎不需要您按照 C
的要求更改整个编程范例。