美文网首页iOS Developer手机移动程序开发
RxSwift之traits前篇:RxSwift traits

RxSwift之traits前篇:RxSwift traits

作者: 逐水而上 | 来源:发表于2017-05-22 11:00 被阅读727次

    注意!以下可能是计算机英语业余水平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)

    相关文章

      网友评论

        本文标题:RxSwift之traits前篇:RxSwift traits

        本文链接:https://www.haomeiwen.com/subject/iekyxxtx.html