加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Monad新解-FRP对比——ReactiveCocoa、RxSwift、Bacon以及背后的

发布时间:2020-12-15 20:36:23 所属栏目:百科 来源:网络整理
导读:ReactiveX Rx的Observable的本质就是一个Event Monad,即上下文(就是图文教程中包裹的盒子)为Event的一个Monad,这里的Event定义,可以对应语言的struct或者enum,包括了next、error和complete三个上下文即可。这里截取的是Swift语言的实现,map方法实现拆

ReactiveX

Rx的Observable的本质就是一个Event Monad,即上下文(就是图文教程中包裹的盒子)为Event的一个Monad,这里的Event定义,可以对应语言的struct或者enum,包括了next、error和complete三个上下文即可。这里截取的是Swift语言的实现,map方法实现拆装箱(类似Optional,即Haskell的Maybe)

public enum Event<Element> {

? ? /// Next element is produced.

? ? case next(Element)

?

?

? ? /// Sequence terminated with an error.

? ? case error(Swift.Error)

?

?

? ? /// Sequence completed successfully.

? ? case completed

}

?

?

extension Event {

? ? /// Maps sequence elements using transform. If error happens during the transform .error

? ? /// will be returned as value

? ? public func map<Result>(_ transform: (Element) throws -> Result) -> Event<Result> {

? ? ? ? do {

? ? ? ? ? ? switch self {

? ? ? ? ? ? case let .next(element):

? ? ? ? ? ? ? ? return .next(try transform(element))

? ? ? ? ? ? case let .error(error):

? ? ? ? ? ? ? ? return .error(error)

? ? ? ? ? ? case .completed:

? ? ? ? ? ? ? ? return .completed

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? catch let e {

? ? ? ? ? ? return .error(e)

? ? ? ? }

? ? }

}

?

?

而Rx的subscribe方法就是一个解包,也就是Monad<Event>.map(),接收一个(Event) -> void的参数。或者使用更一般直观的三个参数onNext: (Element) -> Void、onError: (Error) -> Void、onCompleted: (Void) -> Void方法(在其他语言实践上,RxJS就是三个function参数,而RxJava为了支持Java7可以使用匿名内部类)

理论:

Monad Event <$> subscribe

?

示例:

let subscription = Observable<Int>.interval(0.3)

.subscribe { event in

print(event) // unwraped event

}

?

?

let cancel = searchWikipedia("me")

.subscribe(onNext: { results in

print(results)

},onError: { error in

print(error)

})

?

?

Rx的Operator是Functor,也就是说(Event) -> Event,因此可以通过Monad不断bind你想要的组合子,直到最终符合UI控件需要的数据

理论:

Monad Event >>= map >>= concat >>= filter >>= map <$> subscribe

?

示例:

let subscription = primeTextField.rx.text ? ? ? ? ? // Observable<String>

.map { WolframAlphaIsPrime(Int($0) ?? 0) }? ? ? // Observable<Observable<Prime>>

.concat() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // Observable<Prime>

.filter { $0.isPrime }? ? ? ? ? ? ? ? ? ? ? ? ? // Observable<Prime>

.map { $0.intValue }? ? ? ? ? ? ? ? ? ? ? ? ? ? // Observable<Int>

?

Promise / Future

Promise本质上也是一个Monad,包裹的上下文就是resolve和reject。

你可能反驳说Promise.then(f)中的f,可以是value => value,而并不是一个被Promise包裹的类型啊。但是实际上,由于JavaScript类型的动态性,Promise.then中直接返回value类型是个语法糖罢了,实际上会处理为value => Promise.resolve(value)

Promise.resolve(1)

.then(v => v+1) //便捷写法罢了,返回的是resolved状态的Promise对象

.then(v => Promise.resolve(v+1)) //完整写法

.then(v => Promise.reject(‘error ‘ + v)) //想要返回rejected状态,无便捷方法

.catch(e => console.log(e)) // error 3

?

原理:

Monad Promise >>= then >>= then >>= catch >>= then

示例:

Promise.resolve(1)

? .then(v => {

? ? return v + 1; // 1

? }.then(v =>? {

? ? throw new Error(‘error‘); //reject

? }.catch(e => {

? ? console.log(e); // error

? ? return Promise.resolve(0);

? }.then(v => {

? ? console.log(‘end‘,v); // end 0

? }

?

https://dreampiggy.com/2016/11/17/FRP简介—ReactiveCocoa、RxSwift、Bacon以及背后的Functional/

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读