如何获得 iOS 13 的 SubscribeOn flatMap 运算符?

How to get SubscribeOn flatMap operator for iOS 13?

此代码无法在 iOS 13 上编译,因为 flatMap 仅在 iOS 中可用 14. 如何扩展 SubscribeOn 以获得 flatMap 运算符?

func f1(_ value: Int) -> Future<Int, Error> {
    Future { promise in
        print("\(Thread.current): f1() value = \(value)")
        promise(.success(value + 1))
    }
}

func f2(_ value: Int) -> Future<Int, Error> {
    Future { promise in
        print("\(Thread.current): f2() value = \(value)")
        promise(.success(value + 1))
    }
}

let a1 = Just(0)
    .subscribe(on: DispatchQueue.global())
    .flatMap(f1)
    .flatMap(f2)
    .receive(on: DispatchQueue.main)
    .sink { _ in
        print("\(Thread.current): completed")
    } receiveValue: { value in
        print("\(Thread.current): sink() value = \(value)")
    }

更新 这是我的解决方案现在的样子:

extension Publishers.SubscribeOn {
    func myFlatMap<P>(_ transform: @escaping (Self.Output) -> P) -> Publishers.FlatMap<P, Publishers.SetFailureType<Self, P.Failure>> where P: Publisher {
        Publishers.FlatMap<P, Publishers.SetFailureType<Self, P.Failure>>(
            upstream: Publishers.SetFailureType<Self, P.Failure>(upstream: self),
            maxPublishers: .unlimited,
            transform: transform
        )
    }
}

aflatMap运算符在iOS13中可用,但还有moreflatMap 运算符在 iOS 14.

中可用

具体来说,the only flatMap operator available in iOS 13要求上游发布者(在你的例子中,Just<Int>)和内部发布者(在你的例子中,Future<Int, Error>)具有相同的Failure 类型。但是 Just<Int>.FailureNever,而 Future<Int, Error>.FailureError

在iOS14中,额外重载了三个flatMap,用于三种情况的特殊处理:

您的示例代码属于第一种特殊情况(上游 FailureNever),因此它针对 iOS 14 进行编译,但不针对 iOS 13 进行编译。

您可以通过使用 setFailureType 运算符显式转换 Just 来解决此问题:

let a1 = Just(0)
    .setFailureType(to: Error.self)
    .subscribe(on: DispatchQueue.global())
    .flatMap(f1)
    .flatMap(f2)
    .receive(on: DispatchQueue.main)
    .sink { _ in
        print("\(Thread.current): completed")
    } receiveValue: { value in
        print("\(Thread.current): sink() value = \(value)")
    }

或者,您可以使用 Result.Publisher 从必要的 Failure 类型开始 Error。 Swift 甚至应该可以为你推导出来:

let a1 = Result.success(0).publisher
    .subscribe(on: DispatchQueue.global())
    .flatMap(f1)
    .flatMap(f2)
    .receive(on: DispatchQueue.main)
    .sink { _ in
        print("\(Thread.current): completed")
    } receiveValue: { value in
        print("\(Thread.current): sink() value = \(value)")
    }