【问题标题】:Swift Optimise nested async callsSwift 优化嵌套异步调用
【发布时间】:2020-07-15 00:37:00
【问题描述】:

我有这种情况,我需要进行 3 次嵌套异步调用来接收我想要的数据。 所以第二个调用需要第一个调用的数据,第三个调用需要第二个调用的数据。我没有很多这样的案例。只有这个和另一个只有两个嵌套调用,所以我正在考虑一个没有任何外部库的纯粹快速解决方案,但我对一切都持开放态度。

由于我使用的是 Firebase,是否将此逻辑移至 CloudFunctions 会更好?那么要在后端准备呢?

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
            }
        }

    }
}

【问题讨论】:

  • 其实看了你的问题后,我觉得你不需要我的解决方案……答案是:是的,最好把这个逻辑移到后端
  • 这个逻辑不能移动到后端有什么原因吗?我建议调用一个 API,它会为您执行所有这些嵌套调用,为了对话,即使您能够以某种方式进行嵌套调用,那么如果 3 个中的任何一个或两个或所有调用失败,会发生什么情况?您需要编写大量管道代码来处理此处的错误

标签: ios swift firebase asynchronous google-cloud-firestore


【解决方案1】:

如果您不使用 3rd 方库,那么您可能需要考虑将这些操作包装在某个类中,并以命令式的方式使用闭包。

这里是示例:

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)
        }
    }

}

这是上面CustomFirestoreHandler的用法:

let firestoreHandler = CustomFirestoreHandler()
firestoreHandler.executeQuery { (result: Result<Package, Error>) in
    // Handle `result` here...
}

我知道它看起来很复杂,但这是我目前认为 (CMIIW) 防止末日金字塔的唯一方法,因为 swift 没有异步等待样式(就像 javascript 一样)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多