以下管道:
enum MyError: Error { case oops } let cancel = Fail<Int, Error>(error: MyError.oops) .print("1>") .print("2>") .sink(receiveCompletion: { status in print("status>", status) }) { value in print("value>", value) }输出:
1>: receive subscription: (Empty) 2>: receive subscription: (Print) 2>: request unlimited 1>: request unlimited 1>: receive error: (oops) 2>: receive error: (oops) status> failure(__lldb_expr_126.MyError.oops)问题
但是,如果我在前一个管道中插入 receive(on:)运算符:
enum MyError: Error { case oops } let cancel = Fail<Int, Error>(error: MyError.oops) .print("1>") .receive(on: RunLoop.main) .print("2>") .sink(receiveCompletion: { status in print("status>", status) }) { value in print("value>", value) }输出为:
1>: receive subscription: (Empty) 1>: receive error: (oops)receive 操作符似乎使管道短路.我还没有看到其他发布者会发生这种情况,只是当我使用 Fail 或 PassthroughSubject 发布者时.
The receive operator seems to short-circuit the pipeline. I haven't seen it happen for other publishers, just when I use a Fail or PassthroughSubject publisher.
这是预期的行为吗?如果是这样,原因是什么?
下面是创建与 receive(on:)发布者一起使用的失败发布者的示例:
Here's an example of creating a failing publisher that works with the receive(on:) publisher:
struct FooModel: Codable { let title: String } func failPublisher() -> AnyPublisher<FooModel, Error> { return Just(Data(base64Encoded: "")!) .decode(type: FooModel.self, decoder: JSONDecoder()) .eraseToAnyPublisher() } let cancel = failPublisher() .print("1>") .receive(on: RunLoop.main) .print("2>") .sink(receiveCompletion: { status in print("status>", status) }) { value in print("value>", value) } 推荐答案您可能会遇到这篇文章.显然, receive(on:)将通过给定的调度程序异步发送 all 消息,包括订阅消息.因此,发生的事情是在订阅事件有机会被异步发送之前发送了错误,因此当下一个事件出现时,没有订阅者附加到 receive 发布者.
It's possible you're running into the same problem discussed in this post. Apparently receive(on:) will send all messages asynchronously via the given scheduler, including subscription messages. So what's happening is the error is sent before the the subscription event has a chance to be sent asynchronously, and so there is no subscriber attached to the receive publisher when the next event comes in.
但是,看来他们在 iOS 13.3的开发人员beta 1 :
从iOS 13.3(以及其他平台的相关发行版)的开发人员beta 1开始,我们已更改了receive(on :)以及其他Scheduler运算符的行为,以同步向下游发送其订阅.以前,他们会将其异步"到提供的调度程序中.
As of developer beta 1 of iOS 13.3 (and associated releases for other platforms), we've changed the behavior of receive(on:) plus other Scheduler operators to synchronously send their subscription downstream. Previously, they would "async" it to the provided scheduler.
更多推荐
为什么Combine的receive(on :)运算符会误入错误?
发布评论