基于推和基于拉的结构(如 IEnumerable<T> 和 IObservable<T>)之间有什么区别
What is difference between push based and pull based structures like IEnumerable<T> and IObservable<T>
在每个技术讲座或每个博客中 post 我读过 IEnumerable 和 IObservable 我读过,
IEnumerable 是基于拉的结构并且
IObservable 是基于推送的结构。
我读过 IObservable 我们有异步调用,其中没有任何阻塞,一切都是基于推送的。
但是,但是,但是...
这到底是什么意思?基于推和基于拉
因为在我看来 IEnumerable 我们还可以将数据推送到结构中并从中提取数据,我真的迷失了那些技术术语和想法。
请以正常和人性化的方式向我解释这两种结构之间的区别以及基于推和基于拉的结构之间的区别。
谢谢。
Please in a normal and human way explain to me the difference
好的,让我们干杯吧。这是我做的最正常的人类行为。
基于拉取:
// I want some toast. I will pull it out of the toaster when it is done.
// I will do nothing until the toast is available.
Toast t = toaster.MakeToast();
t.AddJam();
// Yum.
基于推送:
// I want some toast. But it might take a while and I can do more work
// while I am waiting:
Task<Toast> task = toaster.MakeToastAsync();
Toast t = await task;
// await returns to the caller if the toast is not ready, and assigns
// a callback. When the toast is ready, the callback causes this method
// to start again from this point:
t.AddJam();
// Yum.
你想提取一个结果,调用一个函数,然后在函数 returns 之前什么都不做。
你想要一个结果推送给你,你调用一个异步函数并等待结果。当结果可用时,它会被推送到回调中,回调会在需要的地方恢复方法。
IEnumerable<T>
只是一系列拉;每次要提取结果时调用 MoveNext
并得到 T
。 IObservable<T>
只是一系列推送;您注册一个回调,每次有新的 T
可用时都会调用它。
换句话说:IEnumerable<T>
在逻辑上是一系列 Func<T>
调用 。 IObservable<T>
在逻辑上是 Task<T>
延续 的序列。不要让它们是 序列 这一事实让您感到困惑;那是偶然的。基本思想是函数是同步的;你调用它们并得到一个结果同步;如果需要一段时间,请等待。任务是异步的;你启动它们并在结果可用时异步得到结果。
这个想法在 IObservable
和 await
之前就存在于 C# 中。另一种看待方式是:基于拉的就像函数调用,基于推的就像事件处理程序。一个普通的函数调用,当你想要什么的时候调用它。事件处理程序,它会在发生某些事情时调用您。 事件是 C# 语言本身表示观察者模式的方式。但是事件总是在逻辑上形成一个 序列 ,因此能够像操作拉取项序列一样操作推入项序列是有意义的。因此,发明了 IObservable
。
假设有一个(逻辑)服务器和一个客户端,谁来决定何时传递数据,是服务器还是客户端?
Pull-based 描述了一种客户端-运行 方案:客户端发出请求,数据立即提供。基于推送描述了一种服务器-运行 方案:客户端可以连接到推送流 (IObservable),但它们不能请求数据,它们在服务器想要提供数据时获取数据。
拉取的规范形式是数据库查询:您向服务器发送请求,服务器以项目集合作为响应。推送的规范版本将是一个聊天应用程序:聊天客户端不能 'demand' 新的对话数据,服务器会在对方说了什么时告诉你。
除了上面的好答案,我还会提供以下内容:
- 'IEnumerable' 意味着 'enumerable' 在 .NET Framework 概念模型中与 'pull based' 隐式混淆。它的意思是 "allows you to get an enumerator, which allows you pull the next value"
- 但我们也有 IAsyncEnumerable。
- 在数学上,可枚举的意思是 'countable,' 即可数集。
- Observable 也可能是可数的,因为一个 Observable 可能代表一组离散事件。
命名混乱,在我看来不能很好地表达他们想要表达的概念。例如,在 Java 世界中,IEnumerable 是 Iterable,这更接近 .NET 中的意图。
我认为将 IEnumerable 和围绕它们的 LINQ 构造想象为 "Get me some data from some source and filter/group them like this..." 是最简单的,而 Observables 可以被认为是您可以对其做出反应的传入流。我认为将 observables 视为延续不一定有帮助。
A man walks into a grocery store and asks the shopkeeper if he has any eggs. "Yes," says the shopkeeper. "May I have some?" asks the man. And the shopkeeper gives the man some eggs. "Do you have any more?" asks the man. "Yes," says the shopkeeper. "May I have some?" asks the man. And the shopkeeper gives the man some eggs. "Do you have any more?" asks the man. "No," says the shopkeeper. The man leaves.
这是基于拉动的。该男子从店主那里拿 "pulling" 个鸡蛋,直到剩下 none 个为止。
A man walks into a grocery store and asks the shopkeeper if he can delivery any eggs and, if so, can he deliver then whenever he can get them. "Yes," says the shopkeeper. The man leaves. In a few days some eggs arrive. A few more days later some eggs arrive. Then the man calls the shopkeeper and asks the for the deliveries to stop. No more eggs arrive.
这是基于推送的。男人不等店主给他鸡蛋。该男子继续做其他事情,店主 "pushes" 将鸡蛋交给该男子。
在每个技术讲座或每个博客中 post 我读过 IEnumerable 和 IObservable 我读过, IEnumerable 是基于拉的结构并且 IObservable 是基于推送的结构。
我读过 IObservable 我们有异步调用,其中没有任何阻塞,一切都是基于推送的。
但是,但是,但是...
这到底是什么意思?基于推和基于拉
因为在我看来 IEnumerable 我们还可以将数据推送到结构中并从中提取数据,我真的迷失了那些技术术语和想法。
请以正常和人性化的方式向我解释这两种结构之间的区别以及基于推和基于拉的结构之间的区别。
谢谢。
Please in a normal and human way explain to me the difference
好的,让我们干杯吧。这是我做的最正常的人类行为。
基于拉取:
// I want some toast. I will pull it out of the toaster when it is done.
// I will do nothing until the toast is available.
Toast t = toaster.MakeToast();
t.AddJam();
// Yum.
基于推送:
// I want some toast. But it might take a while and I can do more work
// while I am waiting:
Task<Toast> task = toaster.MakeToastAsync();
Toast t = await task;
// await returns to the caller if the toast is not ready, and assigns
// a callback. When the toast is ready, the callback causes this method
// to start again from this point:
t.AddJam();
// Yum.
你想提取一个结果,调用一个函数,然后在函数 returns 之前什么都不做。
你想要一个结果推送给你,你调用一个异步函数并等待结果。当结果可用时,它会被推送到回调中,回调会在需要的地方恢复方法。
IEnumerable<T>
只是一系列拉;每次要提取结果时调用 MoveNext
并得到 T
。 IObservable<T>
只是一系列推送;您注册一个回调,每次有新的 T
可用时都会调用它。
换句话说:IEnumerable<T>
在逻辑上是一系列 Func<T>
调用 。 IObservable<T>
在逻辑上是 Task<T>
延续 的序列。不要让它们是 序列 这一事实让您感到困惑;那是偶然的。基本思想是函数是同步的;你调用它们并得到一个结果同步;如果需要一段时间,请等待。任务是异步的;你启动它们并在结果可用时异步得到结果。
这个想法在 IObservable
和 await
之前就存在于 C# 中。另一种看待方式是:基于拉的就像函数调用,基于推的就像事件处理程序。一个普通的函数调用,当你想要什么的时候调用它。事件处理程序,它会在发生某些事情时调用您。 事件是 C# 语言本身表示观察者模式的方式。但是事件总是在逻辑上形成一个 序列 ,因此能够像操作拉取项序列一样操作推入项序列是有意义的。因此,发明了 IObservable
。
假设有一个(逻辑)服务器和一个客户端,谁来决定何时传递数据,是服务器还是客户端?
Pull-based 描述了一种客户端-运行 方案:客户端发出请求,数据立即提供。基于推送描述了一种服务器-运行 方案:客户端可以连接到推送流 (IObservable),但它们不能请求数据,它们在服务器想要提供数据时获取数据。
拉取的规范形式是数据库查询:您向服务器发送请求,服务器以项目集合作为响应。推送的规范版本将是一个聊天应用程序:聊天客户端不能 'demand' 新的对话数据,服务器会在对方说了什么时告诉你。
除了上面的好答案,我还会提供以下内容:
- 'IEnumerable' 意味着 'enumerable' 在 .NET Framework 概念模型中与 'pull based' 隐式混淆。它的意思是 "allows you to get an enumerator, which allows you pull the next value"
- 但我们也有 IAsyncEnumerable。
- 在数学上,可枚举的意思是 'countable,' 即可数集。
- Observable 也可能是可数的,因为一个 Observable 可能代表一组离散事件。
命名混乱,在我看来不能很好地表达他们想要表达的概念。例如,在 Java 世界中,IEnumerable 是 Iterable,这更接近 .NET 中的意图。
我认为将 IEnumerable 和围绕它们的 LINQ 构造想象为 "Get me some data from some source and filter/group them like this..." 是最简单的,而 Observables 可以被认为是您可以对其做出反应的传入流。我认为将 observables 视为延续不一定有帮助。
A man walks into a grocery store and asks the shopkeeper if he has any eggs. "Yes," says the shopkeeper. "May I have some?" asks the man. And the shopkeeper gives the man some eggs. "Do you have any more?" asks the man. "Yes," says the shopkeeper. "May I have some?" asks the man. And the shopkeeper gives the man some eggs. "Do you have any more?" asks the man. "No," says the shopkeeper. The man leaves.
这是基于拉动的。该男子从店主那里拿 "pulling" 个鸡蛋,直到剩下 none 个为止。
A man walks into a grocery store and asks the shopkeeper if he can delivery any eggs and, if so, can he deliver then whenever he can get them. "Yes," says the shopkeeper. The man leaves. In a few days some eggs arrive. A few more days later some eggs arrive. Then the man calls the shopkeeper and asks the for the deliveries to stop. No more eggs arrive.
这是基于推送的。男人不等店主给他鸡蛋。该男子继续做其他事情,店主 "pushes" 将鸡蛋交给该男子。