Swift - 排队合并请求
Posted
技术标签:
【中文标题】Swift - 排队合并请求【英文标题】:Swift - Queueing Combine Requests 【发布时间】:2021-02-26 13:18:01 【问题描述】:我正在处理一个合并请求,我想在某个事件之后执行或排队执行。下面是场景-
-
新请求已生成。
检查应用是否有访问令牌
如果是,执行请求
如果没有,获取令牌,然后执行请求
下面是我的 API,每个请求都会被触发 -
public func fetchData<T: Codable>(to request: URLRequest) -> AnyPublisher<Result<T>, Error>
if hasToken
return self.urlSession.dataTaskPublisher(for: request)
.tryMap(self.parseJson)
.receive(on: RunLoop.main)
.subscribe(on: DispatchQueue.main)
.eraseToAnyPublisher()
else
// Store request somewhere
// Get token
// Execute stored request
如果有人能建议我如何继续我的代码的 else 部分,我将不胜感激。
【问题讨论】:
这与您的previous question 有何不同?或者您是否希望在收到令牌之前向fetchData
发出多个请求?
我希望提出多个请求。
【参考方案1】:
如果快速连续发生多个请求,您开始使用的方法将不起作用。所有这些请求都会将hasToken
视为false
,并且它们都会发起令牌请求。
您可以创建一个var tokenRequested: Bool
属性并同步对它的访问。
我解决这个问题的方法 - 不确定这是否是最好的方法 - 是创建一个管道,所有请求都将通过该管道排队:
class Service
private let requestToken = PassthroughSubject<Void, Error>()
private let tokenSubject = CurrentValueSubject<Token?, Error>(nil)
var c: Set<AnyCancellable> = []
init()
requestToken.zip(tokenSubject)
.flatMap (_, token) -> AnyPublisher<Token, Error> in
if let token = token
return Just(token).setFailureType(to: Error.self)
.eraseToAnyPublisher()
else
return self.fetchToken()
.eraseToAnyPublisher()
.map $0 as Token?
.subscribe(tokenSubject)
.store(in: &c)
private func fetchToken() -> AnyPublisher<Token, Error>
// async code to fetch the token
通过requestToken
的任何请求都与来自tokenSubject
的值同步,因此第一个请求与初始nil
一起出现,但后续请求会等到发布下一个值,这会在前一个值完成时发生。
然后,要发出请求,您首先要获取令牌getToken()
,然后发出请求。
extension Service
private func getToken() -> AnyPublisher<Token, Error>
// request token, which starts queues it in the pipeline
requestToken.send(())
// wait until next token is available
return tokenSubject
.compactMap $0 // non-nil token
.first() // only one
.eraseToAnyPublisher()
func fetchData<T: Codable>(request: URLRequest) -> AnyPublisher<T, Error>
getToken()
.flatMap token in
// make request
.eraseToAnyPublisher()
【讨论】:
以上是关于Swift - 排队合并请求的主要内容,如果未能解决你的问题,请参考以下文章
AVAudioPlayer 使用数组对音频文件进行排队 - Swift