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

Firebase Completion Handler回调执行顺序异常问题排查

问题根源

Firebase 数据库的observe(_:with:)是异步接口:调用该方法发起数据拉取请求后,当前线程不会阻塞等待数据返回,会直接执行后续代码;等网络请求完成、拿到服务端返回的数据后,才会执行传入的snapshot处理闭包。
你当前的代码把completion(arg)写在了observe闭包的外部,会在发起Firebase请求后立刻触发completion回调,根本不会等待数据拉取和解析完成,因此出现执行顺序和预期不符的问题。

修复方案

将completion调用移动到Firebase数据处理闭包的内部,等数组追加、数据打印全部完成后,再触发回调。另外异步执行的闭包需要标记@escaping,否则会触发编译错误。
修正后的method方法代码如下:

func method(arg: Bool, completion: @escaping (Bool) -> ()) {
    let userID = Auth.auth().currentUser!.uid
    let database = Database.database().reference()
    database.child("user/\(userID)/abonniertePoi/").observe(.value, with: { snapshot in
        for child in snapshot.children.allObjects as! [DataSnapshot] {
            myFeed.myArray1.append(child.key)
        }
        print(myFeed.myArray1)
        // 所有数据处理完成后再执行回调
        completion(arg)
    })
}

修改后执行顺序会完全符合预期:

  1. 发起Firebase数据拉取
  2. 拉取完成后遍历快照、给数组追加元素、打印数组内容
  3. 执行completion闭包,先打印Second line of code executed,再根据参数打印true/false
注意事项
  • 所有网络请求、IO操作类的接口绝大多数都是异步实现的,不能按照同步代码的线性顺序逻辑来写,依赖异步返回结果的逻辑必须放在对应的回调闭包内执行。
  • @escaping标记的作用是告诉编译器,这个闭包会在函数返回之后才被调用,需要注意闭包内的对象引用关系,避免循环引用。

内容的提问来源于stack exchange,提问作者submariner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 05:39:39