RxSwift之traits前篇:RxSwift traits

注意!以下可能是计算机英语业余水平coder翻译,欢迎品鉴,如有不当,留言改删!谢谢。
原文在这里:Traits (formerly Units)

Traits (formerly Units)


这篇文章将要试图描述traits是什么,为什么它是个有用的概念以及怎样构造和运用它。

总则


为什么

Swift强大的类型系统能够用来提升程序的正确性和稳定性,并且使得使用Rx更加简洁和直观。

和原始的Observable相比,Traits有助于跨接口边界沟通和确保可观察序列属性,而且提供上下文含义、语法糖,目标是更具体的用例,而Observable则能够用于任何的上下文环境。因此,Traits是完全可选的,你可以在你程序的任何地方自由使用原始的Observable序列,因为所有的RxSwift/RxCocoa核心APIs都支持它们。

注意:这篇文章里的一些Traits是专门针对RxCocoa工程的(例如Driver),还有一些是整个RxSwift项目的一部分,然而,同样的原则可以容易地在其他的Rx实践里实现。并不需要使用私有API魔法。

它们怎么工作

Traits仅仅是一个封装的结构体,它具有一个单独的只读Observable序列属性。

struct Single<Element> {
    let source: Observable<Element>
}

struct Driver<Element> {
    let source: Observable<Element>
}
...```
你可以把它们想成是一种针对Observable的建造者模式的实现,当一个Trait被构建出来后,调用`.asObservable()`将会把它转化回普通的可观察序列。

####RxSwift traits
***
#####Single
Single是Observable的一种变体,总是能够保证只发送一个元素或者错误,而不是发送一系列元素。
* 只发送一个元素或者错误
* 不共享副作用

使用Single的一个常见的用例是执行只能返回一个响应或者一个错误的HTTP请求,但是如果你只关心一个单一的元素,而不是一个无限的元素流,一个Single就可以模拟任何用例。
######创建一个Single
创建一个Single和创建一个Observable很相似,下面是一个简单的例子:

func getRepo(_ repo: String) -> Single<[String: Any]> {
return Single<[String: Any]>.create { single in
let task = URLSession.shared.dataTask(with: URL(string: "https://api.github.com/repos/(repo)")!) { data, _, error in
if let error = error {
single(.error(error))
return
}

        guard let data = data,
              let json = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves),
              let result = json as? [String: Any] else {
            single(.error(DataError.cantParseJSON))
            return
        }

        single(.success(result))
    }

    task.resume()

    return Disposables.create { task.cancel() }
}

}```
然后你可以按照以下方式使用它:

getRepo("ReactiveX/RxSwift")
    .subscribe { event in
        switch event {
            case .success(let json):
                print("JSON: ", json)
            case .error(let error):
                print("Error: ", error)
        }
    }
    .disposed(by: disposeBag)

或者按照如下方式使用subscribe(onSuccess:onError:)

getRepo("ReactiveX/RxSwift")
    .subscribe(onSuccess: { json in
                   print("JSON: ", json)
               },
               onError: { error in
                   print("Error: ", error)
               })
    .disposed(by: disposeBag)```
上面的订阅提供了一个`SingleEvent`枚举,可以是`.success`包含了该Single类型的一个元素,或者是`.error`。除了第一个,没有其他的事件会被发送。
在一个原始的Observable序列上使用`.asSingle()`从而把它转化为一个Single也是有可能的。
#####Completable
Completable是Observable的一种变体,它只能完成或者是发送一个错误。它能够保证不发送任何元素。
* 不发送元素
* 发送一个完成事件,或者是一个错误
* 不分享副作用

关于Completable的一个有用的用例是:当我们只关心一个操作已经完成了这个事实,而不关心那个操作完成后生成的元素时,可以用Completable来做模板。你可以拿Completable和`Observable<void>`(Observable<void>不能发送元素)作比较。
######创建一个Completable
创建一个Completable和传建一个Observable相似,下面是一个简单的例子:

func cacheLocally() -> Completable {
return Completable.create { completable in
// Store some data locally
...
...

   guard success else {
       completable(.error(CacheError.failedCaching))
       return Disposables.create {}
   }

   completable(.completed)
   return Disposables.create {}
}

}```
然后你可以像下面这样使用它:

cacheLocally()
    .subscribe { completable in
        switch completable {
            case .completed:
                print("Completed with no error")
            case .error(let error):
                print("Completed with an error: \(error.localizedDescription)")
        }
    }
    .disposed(by: disposeBag)```
或者像下面这样利用`subscribe(onCompleted:onError:) `:

cacheLocally()
.subscribe(onCompleted: {
print("Completed with no error")
},
onError: { error in
print("Completed with an error: (error.localizedDescription)")
})
.disposed(by: disposeBag)```
上面的订阅提供了一个CompletableEvent枚举,该枚举有两个成员:.completed(表明操作没有错误地完成了)和.error。除了第一个事件,其他事件不会再被发送。

Maybe

Maybe是恰好处于Single和Completable之间的一种Observable变体。它可以只发送一个元素,也可以不发送任何元素而完成,或者发送一个错误。
注意:这三种事件中的任何一个都会终止Maybe,也就是说,一个有完成事件的Maybe不能再发送一个元素,一个发送了一个元素的Maybe不能再发送一个完成事件。*

  • 发送一个完成事件,或者一个单一的元素,或者一个错误
  • 不分享副作用

任何可能发送一个元素,但不是必须要发送一个元素的操作都可以用Maybe来做模型。

创建一个Maybe

创建一个Maybe和创建一个Observable类似,下面是一个简单的例子:

func generateString() -> Maybe<String> {
    return Maybe<String>.create { maybe in
        maybe(.success("RxSwift"))

        // OR

        maybe(.completed)

        // OR

        maybe(.error(error))

        return Disposables.create {}
    }
}```
然后你可以像下面这样去使用它:

generateString()
.subscribe { maybe in
switch maybe {
case .success(let element):
print("Completed with element (element)")
case .completed:
print("Completed with no element")
case .error(let error):
print("Completed with an error (error.localizedDescription)")
}
}
.disposed(by: disposeBag)```
或者像下面这样利用subscribe(onSuccess:onError:onCompleted:)来实现:

generateString()
    .subscribe(onSuccess: { element in
                   print("Completed with element \(element)")
               },
               onError: { error in
                   print("Completed with an error \(error.localizedDescription)")
               },
               onCompleted: {
                   print("Completed with no element")
               })
    .disposed(by: disposeBag)```
在一个原始的Observable序列上使用`.asMaybe()`可以转化为一个Maybe。
最后放上整篇翻译的后半部分:[RxSwift之traits后篇:RxCocoa traits](http://www.jianshu.com/p/8e503672588a)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,591评论 18 139
  • 最近在学习RxSwift相关的内容,在这里记录一些基本的知识点,以便今后查阅。 Observable 在RxSwi...
    L_Zephyr阅读 1,739评论 1 4
  • 1.RxSwift初识 RxSwift是 ReactiveX 的swift版本,是一种函数式响应编程的框架。RxS...
    MrMessy阅读 3,159评论 0 11
  • 小县城的夜晚随着夏季的来临开始逐渐变的沸腾起来,道路上车水马龙。 那晚文与我就站在这县城最热闹的街道边,举着招生的...
    L源源阅读 567评论 1 8
  • 今天有朋友问我,是不是和爱人关系不好,我笑了。 其实只是内心有莫名的孤独罢了!
    云之絮语阅读 182评论 0 0