Help us understand the problem. What is going on with this article?

RxSwift 3.3.0で追加された3つのUnit(Single, Maybe, Completable)

More than 3 years have passed since last update.

RxSwift 3.3.0で3つのUnitが追加されました。

  • Single
  • Maybe
  • Completable

RxJavaにあったものが輸入された形のようです。

付属のPlaygroundに例が書かれていなかったので、ざっくりどんなものか確認してみました。
この記事は半分備忘録みたいなものになります。

追記

3.4.0で subscription closures (onSuccess, onError, onCompleted) が実装されました。
やっぱり欲しいよね。プルリク投げてくれたfreak4pcさんありがとう。

Add subscription closures for Single, Maybe and Completable (onSuccess, onError, onCompleted) by freak4pc · Pull Request #1175 · ReactiveX/RxSwift

概要

まず前提として、 ObservableCompleted あるいは Error が流れた時点でそれ以上何も流れなくなりますが、その2つが流れない限り Next は延々と流れてくる可能性があります。

それを踏まえて今回追加された3つのUnitについて見てみると、以下の表のようになります。

Single Maybe Completable
Success ×
Completed ×
Error

Success は 1回だけ流れる Next だと思って下さい。
そのSuccess が流れるのが SingleMaybe です。
MaybeSuccess が流れず、 Completed のみ流れてくる可能性があります。
Completable では Success は流れてきません。

それぞれつくって、実際にどんな風に使えるのか見ていきましょう。

Single

let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Single<String>
    .create(subscribe: { (observer) -> Disposable in
        observer(.success("🐶"))
        observer(.success("🐱")) // ignored
        observer(.error(MyError.unknown)) // ignored
        return Disposables.create()
    })
    .do(onNext: { (value) in
        print("onNext")
    }, onError: { (error) in
        print("onError")
    }, onCompleted: {
        print("onCompleted")
    }, onSubscribe: {
        // subscribe前に実行される 
        print("onSubscribe")
    }, onSubscribed: {
        // subscribe後に実行される 
        print("onSubscribed")
    })
    .subscribe({ (result) in
        switch result {
        case .success(let value):
            print("success: \(value)")
        case .error(let value):
            print("error: \(value)")
        }
    })
    .disposed(by: disposeBag)

追記:3.4.0からは次のようにも書けます

let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Single<String>
    .create(subscribe: { (observer) -> Disposable in
        observer(.success("🐶"))
        observer(.success("🐱")) // ignored
        observer(.error(MyError.unknown)) // ignored
        return Disposables.create()
    })
    .subscribe(onSuccess: { (value) in
        print("success: \(value)")
    }, onError: { (error) in
        print("error: \(error)")
    })
    .disposed(by: disposeBag)

Maybe

let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Maybe<String>
    .create(subscribe: { (observer) -> Disposable in
        observer(.completed)
        observer(.success("🐶")) // ignored
        observer(.error(MyError.unknown)) // ignored
        return Disposables.create()
    })
    .subscribe({ (result: MaybeEvent<String>) in
        switch result {
        case .success(let value):
            print("success: \(value)")
        case .completed:
            print("complete")
        case .error(let error):
            print("error: \(error)")
        }
    })
    .disposed(by: disposeBag)

追記:3.4.0からは次のようにも書けます

let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Maybe<String>
    .create(subscribe: { (observer) -> Disposable in
        observer(.completed)
        observer(.success("🐶")) // ignored
        observer(.error(MyError.unknown)) // ignored
        return Disposables.create()
    })
    .subscribe(onSuccess: { (value) in
        print("success: \(value)")
    }, onError: { (error) in
        print("error: \(error)")
    }, onCompleted: {
        print("complete")
    })
    .disposed(by: disposeBag)

Completable

let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Completable
    .create(subscribe: { (observer) -> Disposable in
        observer(.error(MyError.unknown))
        observer(.completed) // ignored
        return Disposables.create()
    })
    .subscribe({ (result: CompletableEvent) in
        switch result {
        case .completed:
            print("complete")
        case .error(let value):
            print("error: \(value)")
        }
    })
    .disposed(by: disposeBag)

追記:3.4.0からは次のようにも書けます

let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Completable
    .create(subscribe: { (observer) -> Disposable in
        observer(.error(MyError.unknown))
        observer(.completed) // ignored
        return Disposables.create()
    })
    .subscribe(onCompleted: { 
        print("complete")
    }, onError: { (error) in
        print("error: \(error)")
    })
    .disposed(by: disposeBag)

所感

今回追加されたUnitは使いたいシーンが結構ありそうです。
今まで Next が何回流れるか示したい場合はAppleDoc等で分かるようにしないといけませんでした。1回だけで良いのであれば、 SingleMaybe を使えば、ドキュメントに記載しなくても意図が明確になります。

monoqlo
dena_coltd
    Delight and Impact the World
https://dena.com/jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした