美文网首页
Combine 异步事件流的组合和处理

Combine 异步事件流的组合和处理

作者: 大成小栈 | 来源:发表于2024-03-03 21:03 被阅读0次

这段代码是Swift语言中的一段使用Combine框架的代码,主要用于处理异步事件流的组合和处理。

/// 创建一个合并请求
private(set) lazy var combine = CombineAction<String?, (CreateConfigModel?, DetailModel?), APIError> { [unowned self] input in
            let detailSignal = PhotoTalkApi.shared.publisher(.detail, type: JSON.self)
                .tryMap({
                    if let data = try? $0.result?.rawData() {
                        AppDatabase.shared[.talkingDetailData] = data
                        return DetailModel.decode(with: data)
                    } else {
                        throw APIError.undefined
                    }
                }).mapError({
                    APIError(error: $0)
                }).eraseToAnyPublisher()
            
            guard let input else {
                return detailSignal
                    .map({ (nil, $0) }).eraseToAnyPublisher()
            }
            
            let tagSignal = PhotoTalkApi.shared.publisher(.toolTags(route: "phototalk://page/creator/detail?type=\(input)"), type: JSON.self)
                .tryMap({
                    if let data = try? $0.result?.rawData() {
                        AppDatabase.shared[.talkingConfigData(input)] = data
                        return CreateConfigModel.decode(with: data)
                    } else {
                        throw APIError.undefined
                    }
                }).mapError({
                    APIError(error: $0)
                })
                .eraseToAnyPublisher()
            
            return tagSignal.combineLatest(detailSignal)
                .eraseToAnyPublisher()
        }

----------------------------------------------------------------

/// 详情数据 + 配置数据
 combine.values
    .prepend((configModel, detailModel))
    .sink(receiveValue: { [weak self] tuple in
        guard let self else { return }
        // ...
    }).store(in: &cancellables)
/// 错误处理
combine.errors
    .receive(on: DispatchQueue.main)
    .sink(receiveValue: { [weak self] error in
       // ...
    }).store(in: &cancellables)

/// 发起请求
if type == // ... {
    combine.execute(nil)
} else {
    combine.execute(type.value)
}

下面是对代码的详细解读:

private(set) lazy var combine:这是一个懒加载的属性,其类型是CombineAction<String?, (CreateConfigModel?, DetailModel?), APIError>。这个属性使用了private(set),表示在类内部可以读写,但在外部只能进行读取操作。

CombineAction:这是一个自定义的Combine操作符,用于将两个不同类型的Publisher合并到一个Publisher中。它的泛型参数分别是输入类型(String?)、输出类型((CreateConfigModel?, DetailModel?))和错误类型(APIError)。

[unowned self]:这是一个捕获列表,用于避免循环引用。在Combine中,由于可能存在长时间的订阅,需要小心避免循环引用问题。

let detailSignal = ...:这里创建了一个名为detailSignal的Publisher,用于处理获取详细信息的API请求。具体步骤包括:

使用PhotoTalkAPI.shared.publisher创建一个Publisher,订阅了一个名为.detail的API端点,并指定返回类型为JSON。
使用tryMap操作符处理API的结果,将原始数据存储到本地数据库中,然后通过DetailModel.decode将数据解码为DetailModel。
使用mapError操作符将可能的错误映射为APIError。
使用eraseToAnyPublisher将整个操作链转换为AnyPublisher类型。
guard let input else { ... }:这是一个guard语句,用于检查输入是否为nil。如果输入为nil,则直接返回detailSignal的Publisher,其中使用map将输出映射为(nil, $0)。

let tagSignal = ...:这里创建了一个名为tagSignal的Publisher,用于处理获取标签信息的API请求。具体步骤与detailSignal类似。

return tagSignal.combineLatest(detailSignal):使用combineLatest操作符将tagSignal和detailSignal两个Publisher的最新值进行组合,生成一个新的Publisher,其输出类型为元组(CreateConfigModel?, DetailModel?)。

.eraseToAnyPublisher():最后,通过eraseToAnyPublisher将整个操作链转换为AnyPublisher类型,以符合combine属性的类型要求。

eraseToAnyPublisher 的作用:eraseToAnyPublisher 是 Combine 框架中的一个操作符,其主要作用是将一个具体类型的 Publisher 转换为 AnyPublisher 类型。在 Combine 中,AnyPublisher 是一个类型擦除的抽象,用于隐藏底层具体类型,使其更加通用和灵活。

Combine 中的 Publisher 类型是泛型的,它包含了特定的输出类型和错误类型。在某些情况下,你可能想要隐藏具体类型的 Publisher,以便在 API 的设计或函数签名中更加灵活,不暴露太多实现细节。

这是 eraseToAnyPublisher 的一些关键作用:

类型擦除:将一个具体类型的 Publisher 转换为 AnyPublisher,隐藏了底层具体类型,使其在 API 设计中更加通用。

接口灵活性:通过返回 AnyPublisher,可以更轻松地适应接受 Publisher 参数的函数或方法,而无需暴露太多的具体实现细节。

错误处理:AnyPublisher 会擦除具体的错误类型,将其统一为 Swift 的 Error 类型,这可以使错误处理更加灵活,不需要关心具体的错误类型。

示例代码中使用了 eraseToAnyPublisher 主要是为了符合 combine 属性的声明,因为该属性的类型是 CombineAction<String?, (CreateConfigModel?, DetailModel?), APIError>,而 combineLatest 操作返回的 Publisher 的具体类型可能是其他类型,为了满足类型的匹配,使用了 eraseToAnyPublisher 进行类型擦除。这使得 combineLatest(detailSignal, tagSignal) 的返回值变成了 AnyPublisher<(CreateConfigModel?, DetailModel?), APIError>,适应了 combine 属性的声明。

总体而言,这段代码的主要功能是通过Combine框架处理两个异步API请求,将它们的结果合并为一个Publisher,并在最后将整个操作链包装成一个懒加载的属性combine。

相关文章

  • SwiftUI Combine Framework 基础教程

    Combine 通过组合事件处理运算符来定制异步事件的处理。 核心 代码更易于阅读和维护 集中处理事件的代码并消除...

  • SwiftUI(Combine)学习整理(三)

    如果有RxSwift的学习经验那么理解combine会更加迅速 通过对事件处理的操作进行组合 (combine) ...

  • Combine 基础知识

    摘自《SwiftUI和Combine编程》---《Combine异步编程》 响应式异步编程模型 将“状态变化”看作...

  • RxBus基本使用详解

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的API。它组合了观察者模式,迭代器模式和函...

  • RxSwift学习(二)

    前言RxSwift的目的是让数据/事件流和异步任务能够更方便的序列化处理,能够使用Swift进行响应式编程。 本文...

  • SwiftUI 与 Combine(简介)

    SwiftUI 与 Combine(简介)什么是SwiftUI?什么是Combine?响应式编程:异步编程:何时可...

  • DOM事件探秘(一)

    DOM事件学习,事件流、事件处理程序和事件对象 1.事件流 从页面中接收事件的顺序 IE:事件冒泡流即事件最开始由...

  • JS的原生事件

    javascript原生的事件包括事件流、处理函数、事件对象等。而在兼容性也有问题。 1事件流 事件流是ie和Ne...

  • Combine -- 概述

    响应式异步编程的抽象和特点: 异步操作在合适的时机发布事件,这些事件带有数据,使用一个或多个操作来处理这些事件以及...

  • RxSwift学习

    编程思想 用同步的方式,编写处理异步事件的代码。是基于异步 Event(事件)序列的响应式编程。它可以简化异步编程...

网友评论

      本文标题:Combine 异步事件流的组合和处理

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