[英]Swift Optimise nested async calls
I have this case where I need to make 3 nested async calls to receive the data I want.我有这种情况,我需要进行 3 次嵌套异步调用来接收我想要的数据。 So the second call needs data from the first one and the third one needs data from the second one.
所以第二个调用需要第一个调用的数据,第三个调用需要第二个调用的数据。 I do not have a lot of cases like this.
我没有很多这样的案例。 Only this one and another one with only two nested call so I was thinking about a pure swift solution without any external libraries but I'm open to everything.
只有这个和另一个只有两个嵌套调用,所以我在考虑一个没有任何外部库的纯 swift 解决方案,但我对一切都开放。
Since I'm using Firebase, is it better to move this logic to CloudFunctions?由于我使用的是 Firebase,因此将此逻辑移至 CloudFunctions 是否更好? So to prepare it in the backend?
那么要在后端准备它吗?
FirestoreService().fetchCollection(query: query) { (result: Result<[Request], Error>) in
// do stuff
FirestoreService().fetchCollection(query: query) { (result: Result<[Request], Error>) in
// do stuff
FirestoreService().fetchDocument(documentReference: documentReference) { (result: Result<Package, Error>) in
// finish
}
}
}
}
If you don't to used 3rd party library, then probably you want to consider wrap those operations inside some class, and utilise closure in imperative way.如果您不使用 3rd 方库,那么您可能想考虑将这些操作包装在一些 class 中,并以命令式的方式使用闭包。
here is the sample:这是示例:
class CustomFirestoreHandler {
private var onFetchFirstQueryArrived: ((Result<[Request], Error>) -> ())? = nil
private var onFetchSecondQueryArrived: ((Result<[Request], Error>) -> ())? = nil
private var onFetchDocumentArrived: ((Result<Package, Error>) -> ())? = nil
init() {
onFetchFirstQueryArrived = { [weak self] (result: Result<[Request], Error>) in
self?.executeSecondQuery()
}
onFetchSecondQueryArrived = { [weak self] (result: Result<[Request], Error>) in
self?.executeFetchDocument()
}
}
func executeQuery(completion: @escaping (Result<Package, Error>) -> ()) {
self.onFetchDocumentArrived = completion
FirestoreService().fetchCollection(query: query) { [weak self] (result: Result<[Request], Error>) in
// validate if some error occurred and do early return here, so that we don't need necessarily call second query.
if (result.error == whatever) {
self?.onFetchDocumentArrived?(result)
return
}
self?.onFetchFirstQueryArrived?(result)
}
}
private func executeSecondQuery() {
FirestoreService().fetchCollection(query: query) { [weak self] (result: Result<[Request], Error>) in
// validate if some error occurred and do early return here, so that we don't need necessarily call fetch document.
if (result.error == whatever) {
self?.onFetchDocumentArrived?(result)
return
}
self?.onFetchSecondQueryArrived?(result)
}
}
private func executeFetchDocument() {
FirestoreService().fetchDocument(documentReference: documentReference) { (result: Result<Package, Error>) in
self?.onFetchDocumentArrived?(result)
}
}
}
And here's the usage of CustomFirestoreHandler
above:这是上面
CustomFirestoreHandler
的用法:
let firestoreHandler = CustomFirestoreHandler()
firestoreHandler.executeQuery { (result: Result<Package, Error>) in
// Handle `result` here...
}
I know it look complicated, but this is the only way I think (CMIIW) at the moment to prevent pyramid of dooms since swift doesn't have async await style(just like javascript does).我知道它看起来很复杂,但这是我认为(CMIIW)目前防止厄运金字塔的唯一方法,因为 swift 没有异步等待样式(就像 javascript 一样)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.