RxSwift特征序列Single、Maybe、Completable的使用

简介: RxSwift特征序列Single、Maybe、Completable的使用

特征序列(Traits)简介

RxSwift 里面 Observable 也存在一些特征序列,这些特征序列可以帮助我们更准确的描述序列。并且它们还可以给我们提供语法糖,让我们能够用更加优雅的方式书写代码。Single、Completable、Maybe都属于可监听序列(Observable),本文主要介绍这几个的特性以及使用方式以及部分源码解读:


01. Single

1. Single介绍

a. 要么只能发出一个元素

b. 要么产生一个error事件

c. 不会共享附加作用

一个比较常见的例子就是执行 HTTP 请求,然后返回一个应答或错误。不过你也可以用Single来描述任何只有一个元素的序列。


2. Single发送、订阅部分源码解读

从源码可以看到当create的时候只能发送success和failure,在success中调用on(.next(element)后,又立刻调用了on(.completed),则整个过程结束,为什么调用了on(.completed)最后却没收到完成信号?请继续向下看~

public static func create(subscribe: @escaping (@escaping SingleObserver) -> Disposable) -> Single<Element> {
        let source = Observable<Element>.create { observer in
            return subscribe { event in
                switch event {
                case .success(let element):
                    observer.on(.next(element))
                    observer.on(.completed)
                case .failure(let error):
                    observer.on(.error(error))
                }
            }
        }
        return PrimitiveSequence(raw: source)
  }

@frozen public enum Result<Success, Failure> where Failure : Error {
    case success(Success)
    case failure(Failure)
 }

订阅部分仔细看stopped属性会发现,当接收到event后stopped由false改为了true,并且内部判断当为true的时候,直接return了,这就是为什么调用了on(.completed)最后却没收到完成信号?后面的信号Maybe也是类似设计,下文不再重复介绍;

再来看回调可以看到SingleEvent为Result的别名,Result只有success和failure两个值,而订阅的结果为next(Event)和error,不会再执行completed,最后订阅的结果包装成SingleEvent,供外界使用


public func subscribe(_ observer: @escaping (SingleEvent<Element>) -> Void) -> Disposable {
    var stopped = false
    return self.primitiveSequence.asObservable().subscribe { event in
        if stopped { return }
        stopped = true
        switch event {
        case .next(let element):
            observer(.success(element))
        case .error(let error):
            observer(.failure(error))
        case .completed:
            rxFatalErrorInDebug("Singles can't emit a completion event")
        }
    }
}


3. Single的使用

single(.success(100)):发出一个100的元素

single(.failure(TestError.none)):发出一个error信号


Single<Int>.create { (single) -> Disposable in
    single(.success(100))
    // single(.failure(TestError.none))
    return Disposables.create()
}.subscribe { (value) in
    print(value)
} onFailure: { (error) in
    print(error)
} onDisposed: {
    print("onDisposed")
}.disposed(by: disposeBag)

运行结果:



100
onDisposed


02. Completable

1. Completable介绍

a. 不会发出任何元素

b. 发出一个completed事件或者一个error事件

c. 不会共享附加作用

Completable适用于那种你只关心任务是否完成,而不需要在意任务返回值的情况。它和Observable<Void>有点相似。


2. Completable订阅回调部分源码解读

从源码可以看到 CompletableEvent是一个枚举,有error和completed两个值,订阅的结果只有error和completed事件,没有next(Event)事件,并把订阅的结果包装成CompletableEvent,供外界使用

public enum CompletableTrait { }
public typealias Completable = PrimitiveSequence<CompletableTrait, Swift.Never>
@frozen public enum CompletableEvent {
    case error(Swift.Error)
    case completed
}

extension PrimitiveSequenceType where Trait == CompletableTrait, Element == Swift.Never {
    public func subscribe(_ observer: @escaping (CompletableEvent) -> Void) -> Disposable {
    ...
    switch event {
    case .next:
        rxFatalError("Completables can't emit values")
    case .error(let error):
        observer(.error(error))
    case .completed:
        observer(.completed)
    }
}

3. Completable的使用

completable(.completed): 发出完成事件

completable(.error(TestError.none)):发出error事件

Completable.create(subscribe: { (completable) -> Disposable in
    completable(.completed)
    completable(.error(TestError.none))
    return Disposables.create()
}).subscribe {
    print("completed")
} onError: { (error) in
    print(error)
} onDisposed: {
    print("onDisposed")
}.disposed(by: disposeBag)

运行结果:



completedon
Disposed


03. Maybe

1. Maybe介绍

a. 发出一个元素或者一个completed事件或者一个error事件

b. 不会共享附加作用

如果你遇到那种可能需要发出一个元素,又可能不需要发出时,就可以使用Maybe


2. Maybe订阅回调部分源码解读

从源码可以看到CompletableEvent是一个枚举,有success,error和completed三个值,订阅的结果也有next(Event),error和completed事件,一旦收到订阅结果后,后面的就不会再执行,和上文Single设计类似,最后再订阅的结果包装成MaybeEvent,供外界使用

public enum MaybeTrait { }
public typealias Maybe<Element> = PrimitiveSequence<MaybeTrait, Element>
@frozen public enum MaybeEvent<Element> {
    case success(Element)
    case error(Swift.Error)
    case completed
}
extension PrimitiveSequenceType where Trait == MaybeTrait {
    public typealias MaybeObserver = (MaybeEvent<Element>) -> Void
    ...
    public func subscribe(_ observer: @escaping (MaybeEvent<Element>) -> Void) -> Disposable {
        ...
        switch event {
        case .next(let element):
            observer(.success(element))
        case .error(let error):
            observer(.error(error))
        case .completed:
            observer(.completed)
        }
    }
}

3. Maybe的使用

maybe(.success(200)): 发出一个元素

maybe(.completed): 发出完成事件

maybe(.error(TestError.none)):发出error事件

Maybe<Int>.create(subscribe: { (maybe) -> Disposable in
    maybe(.success(200))
    // maybe(.completed)
    // maybe(.error(TestError.none))
    return Disposables.create()
}).subscribe { (element) in
    print(element)
} onError: { (error) in
    print(error)
} onCompleted: {
    print("completed")
} onDisposed: {
    print("onDisposed")
}.disposed(by: disposeBag)

运行结果:



200
onDisposed


总结

Single、Completable、Maybe均不会共享附加作用

1. Single要么只能发出一个元素、要么产生一个error事件

2. Completable不会发出任何元素,只能发出一个completed事件或者一个error事件

3.Maybe只能发出一个元素或者一个completed事件或者一个error事件

相关文章
|
数据处理 对象存储
如何利用 OSS 转换 webp 文件为jpeg
如何利用 OSS 转换 webp 文件为jpeg,OSS 样式使用
2671 1
|
Docker 容器
x86 平台利用 qemu-user-static 实现 arm64 平台 docker 镜像的运行和构建
x86 平台利用 qemu-user-static 实现 arm64 平台 docker 镜像的运行和构建
3986 1
|
监控 Java 应用服务中间件
谈谈你对spring boot 3.0的理解
1. Java 版本要求:Spring Boot 3.0 要求使用 Java 17 或更高版本,这可能会对一些仍在使用旧版 Java 的项目造成兼容性问题。需要确保项目使用的 Java 版本符合要求,并考虑是否需要升级 JDK 版本。 2. 底层依赖项迁移:Spring Boot 3.0 将所有底层依赖项从 Java EE 迁移到了 Jakarta EE API,基于 Jakarta EE 9 并尽可能地兼容 Jakarta EE 10。这可能会对一些使用了 Java EE 的应用造成影响,需要进行相应的修改和调整。 3. 插件和库的支持:尽管 Spring Boot 3.0 支持更多的插件和
2290 0
|
4月前
|
自然语言处理 IDE Java
全新Eclipse 2025 开发工具全方位超详细下载安装教程
Eclipse 2025是免费开源、跨平台的专业IDE,主打Java开发,全面支持Java 24/25预览版;内置AI编程助手(Copilot),性能大幅提升,UI全面现代化;原生多语言支持,插件生态丰富,企业级工具齐全,季度更新,可商用、可深度定制。(239字)
436 0
|
10月前
|
监控 Java Sentinel
Sentinel安装与集成
介绍如何切换hmall-micro项目至dev_02分支并提交代码,强调多分支并行开发模式。随后讲解Sentinel服务保护框架的安装与配置,包括控制台部署、本地运行及项目集成,实现微服务熔断降级,并通过簇点链路监控接口。
Sentinel安装与集成
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
3133 0
|
Oracle 关系型数据库
Oracle中decode 以及ROW_NUMBER() OVER() 函数等其它相关函数用法
Oracle中decode 以及ROW_NUMBER() OVER() 函数等其它相关函数用法
730 0
|
缓存 监控 测试技术
《支付回调状态异常的溯源与架构级修复》
本文复盘了SaaS收银系统微服务架构下,支付回调模块“用户支付成功却显示未付款”异常的排查与解决过程。该系统上线后,仅在每日交易峰值后1小时集中出现异常,常规排查无果。团队通过分布式链路追踪发现,“查询订单详情”接口因多表跨规则分表查询,在峰值后资源竞争下耗时激增,且回调模块无重试机制,导致订单状态更新中断。解决方案从三方面入手:优化接口查询逻辑与分表规则、增强回调模块容错能力、完善全链路监控。上线后异常消失,接口耗时大幅降低,数据库负载下降40%,并总结出微服务跨服务交互的避坑准则,为后端开发者提供参考。
577 4
|
Java API Nacos
|
Java 开发者 数据格式
【Java笔记+踩坑】SpringBoot基础4——原理篇
bean的8种加载方式,自动配置原理、自定义starter开发、SpringBoot程序启动流程解析
【Java笔记+踩坑】SpringBoot基础4——原理篇