我有这样的代码:
import Cocoa
import Combine
func prepareURLRequest(for url: URL) -> URLRequest {
let request = URLRequest(url: url)
var token = "token"
print("start value: \(token)")
let subscription = Token()
subscription.getToken()
.sink(receiveCompletion: { _ in
print("subscription completed")
}, receiveValue: { value in
token = value
print("value received: \(token)")
})
print("new value: \(token)")
// attach received token to request
return request
}
class Token {
let token = PassthroughSubject<String,Never>()
func verify() -> Bool {
// TODO: Token verification logic
Bool.random()
}
func getToken() -> AnyPublisher<String,Never> {
return Future<String, Never> { promise in
if self.verify() {
let url = URLRequest(url: URL(string: "http://avatars.io/twitter/twostraws")!)
URLSession.shared.dataTask(with: url) { data, response, error in
print("Data Task started")
if let error = error {
print("error \(error)")
}
guard let data = data else {
preconditionFailure("data error")
}
guard let response = response as? HTTPURLResponse else {
preconditionFailure("response error")
}
print("data task received response with code: \(response.statusCode)")
promise(.success("\(response.statusCode)"))
}.resume()
} else {
print("keychain path")
sleep(2)
promise(.success("kwychain path success"))
}
}.eraseToAnyPublisher()
}
}
let url = URL(string: "http://avatars.io/twitter/twostraws")!
let request = prepareURLRequest(for: url)
代码应将接收的令牌附加到准备好的请求对象。现在,唯一的verify -> false path
以所需的顺序返回数据。当我尝试在prepareURLRequest结束其生命周期后,verify -> true
路径数据被接收。
如何修复这一问题,使两个路径都有正确的顺序(并且在prepareURLRequest方法结束之前更新令牌?
发布于 2020-03-13 01:03:47
你遇到的问题是,你没有用一个延迟来包装未来。您编写的代码期望在请求请求之前不会进行API调用,但这并不完全是Future的工作方式。
一旦创建了Future,它就会调用它的底层异步API调用来呈现-而你使用的是上面的PassthroughSubject,这意味着当你有一个订阅者请求数据时,它已经被调用了。解决此问题的最好方法是将Future
包装在Deferred
发布服务器中,该发布服务器等待创建它,直到订阅请求数据为止。
这里有an example of wrapping Future with Deferred in the Future reference page of Using Combine,以及更多关于未来如何工作以及其他运营商如何使用它的信息。
https://stackoverflow.com/questions/60601645
复制相似问题