平时在开发的过程中,免不了进行异步编程,比如进行网络请求,以前异步编程的时候主要采用两种方法:
- 通过代理方法,设置代理,实现代理方法。
- 通过闭包block块处理。
采用第一种方法代码分家,不利于维护,有些时候方法名起不好都分辨不出来是内部方法还是代理方法。
采用第二种也有弊端,业务繁琐的话容易多层嵌套,再加上处理不同场景,那代码简直像一锅粥。
而Combine
提供的Future
大大简化了异步编程的代码,更利于维护,那么什么是Future
呢?
引用官方的解释就是:
A publisher that eventually produces a single value and then finishes or fails.
首先是一个Publisher
,发送单一的值,发送完以finish
或者fails
结束。Future
代表将来,意在在将来的某个时间点发送数据给订阅者,多用在异步操作中。
final public class Future<Output, Failure> : Publisher where Failure : Error {
/// A type that represents a closure to invoke in the future, when an element or error is available.
///
/// The promise closure receives one parameter: a `Result` that contains either a single element published by a ``Future``, or an error.
public typealias Promise = (Result<Output, Failure>) -> Void
/// Creates a publisher that invokes a promise closure when the publisher emits an element.
///
/// - Parameter attemptToFulfill: A ``Future/Promise`` that the publisher invokes when the publisher emits an element or terminates with an error.
public init(_ attemptToFulfill: @escaping (@escaping Future<Output, Failure>.Promise) -> Void)
通过定义可知,创建Future
实例的时候组要指定输出的类型和错误类型,在初始化方法中还要实现一个闭包,在闭包内返回一个Promise
对象。
Promise
对象也时候一个闭包,返回Result
枚举类型(成功或者失败),Result
所带的数据类型或者错误类型要和定义Future
的类型保持一致。
我们可以通过初始化Future
的闭包处理异步事件,然后将处理结果通过Promise
发送出去。
初始化一个Future
,并在闭包内返回Int
类型的值。
let future = Future<Int, Never> { promise in
promise(.success(1))
}
初始化一个Future
,并在闭包内返回错误。
struct NetworkError: Error {}
let future = Future<Int, Error> { promise in
promise(.failure(NetworkError()))
}
上面大概了解了Future
和Promise
,现在看看接下来这么用,Promise
发出来一个事件值,那么就要有接收的人,也就是Subscriber
。
class FutureViewModel: ObservableObject {
private var cancellable = Set<AnyCancellable>()
func requestData() {
let fetchFuture = Future<String, Never> { promise in
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 3) {
promise(.success("Hello World"))
}
}
fetchFuture
.sink { completion in
print("---> Received completion: \(completion)")
} receiveValue: { value in
print("---> Received value: \(value)")
}
.store(in: &cancellable)
print("---> last line")
}
}
在FutureViewModel
中定义了一个requestData
方法,方法中创建了一个Future
,并设置了类型,闭包内模拟请求网络数据的情况,3秒后发出获取成功事件,并带上获取到的数据。
随后通过sink
方法添加了订阅者。
执行结果如下:
在sink
方法receiveValue
闭包中收到了Promise
发送的数值,并且接收到值后,执行了Completion
闭包,结束事件流。
如果没有订阅者Subscriber
,那么Promise
发送出来的值就丢弃了,这和我们之前说的Publisher
没有订阅者,那么发送的值就直接丢弃了一样。
最后,希望能够帮助到有需要的朋友,如果觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。