Combine -- 响应式和指令式的桥梁

2021-02-23  本文已影响0人  jancywen

Apple 平台的开发,包括系统级别的 API 和大多数的第三方框架,也都是按照指令式编程的方式来编写的。想要在 Combine 的响应式框架中使用这些指令式的 API,我们需要一些手段来把这些命令转换为合适的 Publisher。

Future

如果订阅和值的发布是同步过程,我们可以直接用Just 将某个值 “包装” 成一个 Publisher 来提供给各类 Publisher 的合并操作
如果我们希望订阅操作和值的发布是异步行为,不在同一时间发生的话,可以使用 Future。Future 提供了一种方式,可以让我们创建一个接受未来的事件的 Publisher。

struct SampleModel {
    var id: Int?
}

func sampleRequestAction(handler: @escaping(SampleModel?, Error?) -> Void) {
    print("模拟延时")
    DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
        print("延时结束返回")
        handler(SampleModel(id: 5), nil)
    }
}

Future<SampleModel, Error> { promise in
    sampleRequestAction { (model, err) in
        print("promise")
        if let model = model {
            promise(.success(model))
        }else {
            promise(.failure(err!))
        }
    }
}
.subscribe(on: RunLoop.main)
.sink { (complete) in
    print("complete")
    if case .failure(let msg) = complete {
        print(msg)
    }
} receiveValue: { (model) in
    print("receiveValue:")
    print(model.id)
}

// 模拟延时
// 延时结束返回
// promise
// receiveValue:
// Optional(5)
// complete

Future 只能为我们提供一次性 Publisher:对于提供的 promise,你只有两种选择:发送一个值并让 Publisher 正常结束,或者发送一个错误。因此,Future 只适用于那些必然会产生事件结果,且至多只会产生一个结果的场景。比如刚才看到的网络请求:它要么成功并返回数据及响应,要么直接失败并给出URLError。

subject

对于可重复的多次发生的事件,可以使用 subject

let subject = PassthroughSubject<(), Never>()
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
    subject.send()
}
上一篇 下一篇

猜你喜欢

热点阅读