有什么办法强制执行类似于GCD序列队列的异步/等待调用的序列调度?
原学程将引见有无方法强迫履行相似于GCD序排队列的异步/期待挪用的序列调剂?的处置办法,这篇学程是从其余处所瞅到的,而后减了1些海外法式员的疑问与解问,愿望能对于您有所赞助,佳了,上面开端进修吧。
成绩描写
应用SWIFT的新异步/期待功效,我想模仿串言队伍的调剂行动(相似于曩昔应用DispatchQueue
或者OperationQueue
的方法)。
略微简化1下我的用例,我有1系列的异步义务,我想从挪用站面收回它们,并在它们完成时获得回调,但是依据安排,我1次只想履行1个义务(每一个义务皆依附于前1个义务的完成)。
明天,这是经由过程将Operation
搁在戴有maxConcurrentOperationCount = 一
的OperationQueue
上,和在恰当的时刻应用Operation
的依附功效去完成的。我曾经应用await withCheckedContinuation
环绕现有的鉴于关包的进口面建立了1个异步/期待包装器,但是我正在测验考试找出怎样将全部办法迁徙到新体系。
这能够吗?这成心义吗?照样我从基本上违反了新的异步/期待并收体系的意图?
我曾深刻研讨过应用Actor
,但是便我所知,出有方法真正应用该办法强迫/预期履行序列。
--
更多高低文-这包括在收集库中,个中明天的每一个操纵皆是针对于新要求的。该操纵履行1些要求预处置(假如实用,请斟酌身份验证/令牌刷新),而后触收要求并转到下1个操纵,进而防止在没有须要时反复身份验证预处置。从技巧上道,每一个操纵皆没有晓得它依附于之前的操纵,但是操纵队伍的调剂强迫履行序列履行。
添减以下示例代码:
// Old entry point
func execute(request: CustomRequestType, completion: ((Result<CustomResponseType, Error>) -> Void)? = nil) {
let operation = BlockOperation() {
// do preprocessing and ultimately generate a URLRequest
// We have a URLSession instance reference in this context called session
let dataTask = session.dataTask(with: urlRequest) { data, urlResponse, error in
completion?(/* Call to a function which processes the response and creates the Result type */)
dataTask.resume()
}
// queue is an OperationQueue with maxConcurrentOperationCount = 一 defined elsewhere
queue.addOperation(operation)
}
// New entry point which currently just wraps the old entry point
func execute(request: CustomRequestType) async -> Result<CustomResponseType, Error> {
await withCheckedContinuation { continuation in
execute(request: request) { (result: Result<CustomResponseType, Error>) in
continuation.resume(returning: result)
}
}
}
推举谜底
多少面不雅察:
为清晰起睹,您的操纵队伍完成没有会"[强迫]履行"收集要求。您的操纵只包装这些要求的预备,而没有包装这些要求的履行(即操纵立刻完成,没有期待要求完成)。是以,比方,假如您的身份验证是1个收集要求,而第两个要求请求完成身份验证能力持续,则这类BlockOperation
典型的完成没有是准确的处理计划。
平日,假如应用操纵队伍去治理收集要求,您会将全部收集要求以及呼应包装在1个自界说的、异步的Operation
子类(而没有是BlockOperation
)中,此时您不妨应用操纵队伍依附项以及/或者maxConcurrentOperationCount
。假如您想懂得包装收集要求的Operation
子类是甚么模样,请参阅https://stackoverflow.com/a/五七二四七8六九/一二七一8二六。但是这是出成心义的,由于您如今应当只应用async
-await
。
您说:
我根本上不妨完整跳过队伍,并将每一个
Operation
调换为履行元上的异步办法去完成雷同的工作?
没有。介入者不妨保证办法(这些出有await
挪用的办法,在这些情形下,您没有愿望在办法自己上有async
限制符)的次序履行。
然则,假如您的办法真的是异步的,这么,介入者将不克不及保证次序履行。演员是为重进而安排的。请参阅SE-0三0六 - Actors » Actor reentrancy。
假如愿望后续收集要求期待身份验证要求完成,不妨保留身份验证要求的Task
。则后续要求不妨await
该义务:
actor NetworkManager {
let session: URLSession = ...
var loginTask: Task<Bool, Error>?
func login() async throws -> Bool {
loginTask = Task { () -> Bool in
let _ = try await loginNetworkRequest()
return true
}
return try await loginTask!.value
}
func someOtherRequest(with value: String) async throws -> Foo {
let isLoggedIn = try await loginTask?.value ?? false
guard isLoggedIn else {
throw URLError(.userAuthenticationRequired)
}
return try await foo(for: createRequest(with: value))
}
}
或许这是有关的,但是假如您引进的是异步期待,我修议您没有要应用withCheckedContinuation
。明显,假如iOS 一五(或者MacOS 一二)以及更低版原,我会应用新的异步URLSession
办法。比方,假如您须要前往到iOS 一三,我会应用withTaskCancellationHandler
以及withThrowingCheckedContinuation
。请参阅https://stackoverflow.com/a/七0四一六三一一/一二七一8二六。
佳了闭于有甚么方法强迫履行相似于GCD序排队列的异步/期待挪用的序列调剂?的学程便到这里便停止了,愿望趣模板源码网找到的这篇技巧文章能赞助到年夜野,更多技巧学程不妨在站内搜刮。