Swift Combine — Future和Promise的使用

平时在开发的过程中,免不了进行异步编程,比如进行网络请求,以前异步编程的时候主要采用两种方法:

  1. 通过代理方法,设置代理,实现代理方法。
  2. 通过闭包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()))
}

上面大概了解了FuturePromise,现在看看接下来这么用,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没有订阅者,那么发送的值就直接丢弃了一样。

最后,希望能够帮助到有需要的朋友,如果觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值