【发布时间】:2020-03-09 14:55:55
【问题描述】:
上下文
我正在遵循 WWDC 2019 722 https://developer.apple.com/videos/play/wwdc2019/722/ 和 WWDC 2019 721 https://developer.apple.com/videos/play/wwdc2019/721/ 的示例,并通过验证在字段上运行异步网络检查。
正如演讲中提到的,用户名字段应该:
- 去抖动
- 显示加载指示器
- 执行网络请求
- 以网络结果结束
- 隐藏加载指示器
- 并根据网络响应显示或隐藏验证消息
我有一个具有去抖动功能的原型,并使用延迟运算符模拟网络请求。大多数情况下,所有这些都运行良好。
let a = $firstName
.debounce(for: .seconds(0.5), scheduler: DispatchQueue.main)
.flatMap { name -> AnyPublisher<String, Never> in
if name == "" {
return Just(name)
.eraseToAnyPublisher()
} else {
return Just(name)
.handleEvents(receiveOutput: { _ in self.isFirstNameLoading = true})
.delay(for: .seconds(2), scheduler: DispatchQueue.main)
.handleEvents(receiveOutput: { _ in self.isFirstNameLoading = false})
.eraseToAnyPublisher()
}
}
.map { name -> Bool in name != "Q" }
.assign(to: \.isFirstNameValid, on: self)
去抖会一直等到输入暂停。 flatMap 充当操作符组合流中的条件分支:如果值为空,则不理会网络请求;否则,如果去抖后该值有值,则执行网络请求。最后,我的例子是“Q”总是一个错误,用于模拟目的。
但是,小问题是去抖发生在分支之前。我想将 debounce 移到条件的 else 分支,就像这样。
let a = $firstName
.flatMap { name -> AnyPublisher<String, Never> in
if name == "" {
return Just(name)
.eraseToAnyPublisher()
} else {
return Just(name)
.debounce(for: .seconds(0.5), scheduler: DispatchQueue.main)
.handleEvents(receiveOutput: { _ in self.isFirstNameLoading = true})
.delay(for: .seconds(2), scheduler: DispatchQueue.main)
.handleEvents(receiveOutput: { _ in self.isFirstNameLoading = false})
.eraseToAnyPublisher()
}
}
.map { name -> Bool in name != "Q" }
.assign(to: \.isFirstNameValid, on: self)
出现这种情况时,条件的真分支(空输入)运行正确,而flatMap之后的map+assign运行正确。但是,当输入有值并且条件的 else 分支运行时,去抖动之后什么都不会运行。
我尝试将DispatchQueue 切换为OperationQueue.main 和RunLoop.main 无济于事。
在条件工作之前保持去抖动现在可以,但我想知道我是否在尝试将其放入分支时做错了什么。我还想知道这是否是使用 Combine 在运算符中进行“分支”的正确方法,尤其是在我使用 flatMap 和 Just() 时。
任何帮助将不胜感激!
【问题讨论】: