【问题标题】:Why does Combine's receive(on:) operator swallow errors?为什么 Combine 的 receive(on:) 操作符会吞下错误?
【发布时间】:2020-03-15 16:12:43
【问题描述】:

以下管道:

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 运算符似乎使管道短路。我还没有看到其他发布者发生这种情况,就在我使用FailPassthroughSubject 发布者时。

这是预期的行为吗?如果有,是什么原因造成的?


解决方法

以下是创建与 receive(on:) 发布者一起使用的失败发布者的示例:

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)
}

【问题讨论】:

    标签: swift combine


    【解决方案1】:

    您可能遇到this post 中讨论的相同问题。显然receive(on:) 将通过给定的调度程序异步发送 所有 消息,包括订阅消息。所以发生的事情是在订阅事件有机会异步发送之前发送错误,因此当下一个事件到来时,没有订阅者附加到receive 发布者。

    但是,从developer beta 1 of iOS 13.3 开始,他们似乎正在改变这一点:

    从 iOS 13.3 的开发者 beta 1(以及其他平台的相关版本)开始,我们更改了 receive(on:) 以及其他调度器操作符的行为,以同步向下游发送他们的订阅。以前,他们会将其“异步”到提供的调度程序。

    【讨论】:

    • 啊哈!因此,解决方法可能有效的原因是.decode(type:decoder:) 正在异步发送它的消息。
    • 嗯,也许吧。我不知道,decode 的文档没有提到异步运行。 tbh 我不清楚为什么您的解决方法有效
    猜你喜欢
    • 2021-08-03
    • 2013-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-08
    • 1970-01-01
    • 1970-01-01
    • 2021-04-27
    相关资源
    最近更新 更多