Leaving the monad
What is a monad
monad是一个有效的编程结构,与其他结构相比:
- Data structure(数据结构):Purely state e.g. a List, a Tree or a Tuple(纯状态,例如list、Tree或Tuple)
- Contract:Contract definition or abstract functionality e.g. an interface or abstract class(例如接口或抽象类)
- Object-Orientated structure(面向对象的结构):State and behavior together 结合状态与行为
通常一个monadic允许连接together操作来产生一个管道,就像使用扩展方法。
Monads是一种抽象的数据类型构造函数,在领域模型中封装程序逻辑而不是数据。
基于维基百科中的定义,可以将队列看做monads,在这种情况下抽象数据类型是IObservable<T>。当我们使用一个可观测物队列,我们在抽象数据类型IObservable<T>的上组合功能进行查询,这个查询成为了我们封装的逻辑。
使用monads来定义控制流是非常有用的,特别是在处理典型的编程问题,例如IO\并发和错误处理的时候,而这正是RX的强项。
Why leave the monad?
出于各种不同的原因,你可能想在不同的范式中消耗可观测物队列。需要暴露其功能给外部的库可能需要将其以事件或Task的实例进行呈现。
使用阻塞方法来限制异步移动部件的数量有助于降低RX的学习曲线。
在生产代码中,很少建议“打破monad”,尤其是在从可观测物队列移动到阻塞方法的情况下。在同步和异步范式间切换时应该格外谨慎,例如死锁和可扩展性等问题是常见并发问题的根源。
本章将学习RX中允许你离开IObservable<T> monad的那一部分。
ForEach
ForEach方法提供了一种接收元素的方式(和Subscribe方法类似),ForEach和Subscribe之间的关键区别是ForEach会阻塞当前线程直到队列完成。
Output:
received 0 @ 01/01/2012 12:00:01 a.m.
received 1 @ 01/01/2012 12:00:02 a.m.
received 2 @ 01/01/2012 12:00:03 a.m.
received 3 @ 01/01/2012 12:00:04 a.m.
received 4 @ 01/01/2012 12:00:05 a.m.
completed @ 01/01/2012 12:00:05 a.m.
ForEach方法只有一个重载,接受一个Action<T>委托作为唯一的参数。在以前的版本中,ForEach有许多重载,现在已经被取消了。你可以在ForEach调用后立即place(放置?)调用,同时OnError处理可以像在其他任何同步代码中使用try/catch一样被标准的Structured Exception Handling(结构化异常处理)取代。
Output:
error @ 01/01/2012 12:00:00 a.m. with Fail
completed @ 01/01/2012 12:00:00 a.m.
上面的例子用try代替了OnNext,catch代替了OnError,finally代替OnConpleted。
ForEach方法像其他的阻塞方法(例如First和Last)一样,应该谨慎使用。for spikes(?)我们将暂时离开ForEach方法,讨论在并发中引入阻塞调用的问题。
ToEnumerable
另一个离开IObservable<T>的方法是调用ToEnumerable方法,下面是一个简单的例子:
Output:
0
1
2
3
4
done
源队列将会在你开始枚举队列的时候被订阅(即:惰性),与ForEach方法相反,ToEnumerable方法意味着只在当你试图移动到下一个元素且它不可用的情况下阻塞。此外,如果序列生产的值比你小号的速度快,这些值将会被缓存。
为处理错误,你可以用一个try/catch域包裹foreach循环,就像你处理其他任何枚举队列一样:
standard warning将适用于从push移动到pull model(无阻塞到阻塞)的情况。
暂无关于此日志的评论。