Swift中使用PromiseKit的when方法处理Firebase数据请求问题
Got it, let's break down how to fix this PromiseKit + Firebase issue you're facing. The core problem here is that your final method is running before all your Firebase requests finish populating the array—either because you're not chaining promises correctly, or misunderstanding how when works for sequential vs parallel tasks.
First, let's clarify two key scenarios you might be dealing with:
1. You need to make Firebase requests sequentially (one after another)
This is common if each request depends on the result of the previous one, or you explicitly need to avoid hitting Firebase with parallel calls.
First, wrap your Firebase request in a reusable Promise function:
import PromiseKit import FirebaseFirestore struct DataModel: Codable { // Your model properties here } func fetchSingleData(fromFirestoreWithID id: String) -> Promise<DataModel> { return Promise { seal in Firestore.firestore() .collection("your_collection") .document(id) .getDocument { snapshot, error in if let error = error { seal.reject(error) return } guard let snapshot = snapshot, let data = try? snapshot.data(as: DataModel.self) else { seal.reject(NSError(domain: "FirebaseError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to parse data"])) return } seal.fulfill(data) } } }
Then, use chained then calls to execute requests in order, and populate your array step-by-step. For dynamic lists of IDs, use reduce to build the promise chain:
var yourDataArray: [DataModel] = [] let targetIDs = ["id_1", "id_2", "id_3"] // Your list of Firebase document IDs // Build a sequential promise chain with reduce targetIDs.reduce(Promise<Void>.value(())) { currentPromise, id in currentPromise.then { fetchSingleData(fromFirestoreWithID: id) }.done { fetchedData in yourDataArray.append(fetchedData) } }.done { // All sequential requests are done, array is fully populated self.executeYourFinalMethod() }.catch { error in // Handle any failure in the chain print("Request failed: \(error.localizedDescription)") }
2. You can make requests in parallel (no order dependency)
If you don't care about the order of requests and just need to wait for all to finish, this is where when(fulfilled:) shines. It waits for all promises in an array to resolve before proceeding:
let targetIDs = ["id_1", "id_2", "id_3"] // Map IDs to an array of promises let fetchPromises = targetIDs.map { fetchSingleData(fromFirestoreWithID: $0) } // Wait for all promises to fulfill when(fulfilled: fetchPromises).done { allFetchedData in // allFetchedData is an array of DataModel, ordered to match targetIDs yourDataArray = allFetchedData self.executeYourFinalMethod() }.catch { error in // Triggered if ANY promise in the array rejects print("One or more requests failed: \(error.localizedDescription)") }
Why your original code was resolving early
Chances are you either:
- Didn't properly wrap your Firebase calls in promises (e.g., resolving the promise before Firebase's completion handler ran)
- Used
whenwith promises that weren't correctly chained for sequential work - Accidentally called your final method outside the
doneblock (which only runs after all promises resolve)
Always remember: PromiseKit's done (or then) blocks are the only safe places to run code that depends on the promise resolving. Never execute dependent code outside these blocks!
内容的提问来源于stack exchange,提问作者Chris

