Ios 如何防止多次调用异步函数,但每次都要调用完成?
这是我目前使用的代码:Ios 如何防止多次调用异步函数,但每次都要调用完成?,ios,swift,rx-swift,Ios,Swift,Rx Swift,这是我目前使用的代码: typealias ResponseHandler = (SomeResponse?, Error?) -> Void class LoginService { private var authorizeTokenCompletions = [ResponseHandler]() func authorizeToken(withRefreshToken refreshToken: String, completion: @escaping Resp
typealias ResponseHandler = (SomeResponse?, Error?) -> Void
class LoginService {
private var authorizeTokenCompletions = [ResponseHandler]()
func authorizeToken(withRefreshToken refreshToken: String, completion: @escaping ResponseHandler) {
if authorizeTokenCompletions.isEmpty {
authorizeTokenCompletions.append(completion)
post { [weak self] response, error in
self?.authorizeTokenCompletions.forEach { $0(response, error) }
self?.authorizeTokenCompletions.removeAll()
}
} else {
authorizeTokenCompletions.append(completion)
}
}
private func post(completion: @escaping ResponseHandler) {
// async
completion(nil, nil)
}
}
上面的代码是什么意思
let service = LoginService()
service.authorizeToken(withRefreshToken: "") { a, b in print(a)}
service.authorizeToken(withRefreshToken: "") { a, b in print(a)}
service.authorizeToken(withRefreshToken: "") { a, b in print(a)}
service.authorizeToken(withRefreshToken: "") { a, b in print(a)}
service.authorizeToken(withRefreshToken: "") { a, b in print(a)}
以上所有填写内容均应打印第一次调用的结果
是否可以使用RxSwift执行此操作
PS:一旦有可能,我将奖励100英镑的奖金给帮助我的人;) 回答
是否可以使用RxSwift执行此操作
这是不可能的,因为每次我们触发函数时,它都会被调度,我们无法访问来自其他线程的回调
在创建竞争条件时,解决方法是在一个单例中填充一次数据,而不是多次调用该函数,而是使用该单例
其他一些方法也可能有效,singleton只是一个例子
竞态条件:竞态条件是当一系列操作的预期完成顺序变得不可预测,导致程序逻辑最终处于未定义状态时发生的情况
是否可以使用RxSwift执行此操作
是的,这是可能的
最简单的解决方案:
func authorizeToken(withRefreshToken refreshToken: String) -> Observable<SomeResponse> {
Observable.create { observer in
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
print("async operation")
observer.onNext(SomeResponse())
}
return Disposables.create()
}
}
let response = authorizeToken(withRefreshToken: "")
.share(replay: 1)
response.subscribe(onNext: { print($0) })
response.subscribe(onNext: { print($0) })
response.subscribe(onNext: { print($0) })
response.subscribe(onNext: { print($0) })
response.subscribe(onNext: { print($0) })
我认为这是不可能的,因为每次我们触发函数时,它都会被调度,我们无法访问来自其他线程的回调。为什么不将数据推送到单例而不是多次调用它呢?您当前的代码具有明显的竞争条件、不安全的多线程数组操作,并且不会阻止多次调用
post
,但您可能知道所有这些。虽然可能有一种方法可以让rx swift实现您想要的功能,但您可以让您的完成处理程序数组更新线程安全,并使用调度信号量查看帖子是否已经运行。@Paulw11确切地说,我只是在回答中指出了这一点,但是,阻止帖子再次运行不是他不想做的吗?不,需求中的第二点是,任何时候都只有一个post
实例运行。@Paulw11哦,我没有注意到,是的,你是对的。但是这将如何有助于通过第一次post
结果进行回访,您可以添加一个答案吗?回访完成的顺序对我来说并不重要…因此这可能不是竞争条件。是的,但您正在尝试访问正在进行的任务,并根据第一次回访结果修改它们,我认为,即使使用信号灯,也不可能一次推一个帖子感谢you@Bartłomiejsemanńczyk Paulw11可以有另一个解决办法,但目前是的,我猜这可能就是它。
let response = authorizeToken(withRefreshToken: "")
.replayAll()
let disposable = response.connect() // this calls the async function. The result will be stored until `disposable.dispose()` is called.
response.subscribe(onNext: { print($0) })
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
response.subscribe(onNext: { print($0) }) // this won't perform the async operation again even if the operation completed some time ago.
}