Swift Оптимизация вложенных вызовов asyn c - PullRequest
2 голосов
/ 03 апреля 2020

У меня есть такой случай, когда мне нужно сделать 3 вложенных асинхронных вызова c, чтобы получить нужные мне данные. Таким образом, для второго вызова нужны данные из первого, а для третьего - данные из второго. У меня не так много таких случаев. Только этот и другой с двумя вложенными вызовами, так что я думал о чисто быстром решении без каких-либо внешних библиотек, но я открыт для всего.

Поскольку я использую Firebase, лучше ли перенести этот лог c в 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
            }
        }

    }
}

1 Ответ

1 голос
/ 03 апреля 2020

Если вы не используете стороннюю библиотеку, то, возможно, вы захотите обернуть эти операции внутри некоторого класса и использовать замыкание императивным образом.

вот пример:

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) на данный момент - предотвратить пирамиду гибели с тех пор, как быстро не имеет асин c стиль ожидания (как у javascript).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...