You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中使用PromiseKit的when方法处理Firebase数据请求问题

Fixing PromiseKit Sequential Firebase Requests & Early Resolution

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 when with promises that weren't correctly chained for sequential work
  • Accidentally called your final method outside the done block (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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:11:32