如何修复Firebase的异步问题 [英] How to fix the async issue of firebase
问题描述
我正在尝试查询数据并将其更新到Firebase.但是我无法获取数据.似乎程序没有遇到ref.observeSingleEvent 我该怎么做才能解决此问题?
Im trying to query and update data to firebase. But I cannot get the data. It seems the program doesn't run into ref.observeSingleEvent what should I do to fix this?
func getId(path:String, value:String?, completion: @escaping (String?) -> Void) {
let ref = Database.database().reference(withPath: path).queryOrdered(byChild: "name").queryEqual(toValue: value)
ref.observeSingleEvent(of: .childAdded, with: { snapshot in
print("running in getId")
completion(snapshot.key)
}) { (error) in
print(error.localizedDescription)
}
}
@objc func onTapConfirmed(){
self.getId(path: "patients", value: self.kardex?.patient?.name) { snapshotKey in
BookingViewController.kardexDict["patient"] = snapshotKey as AnyObject?
print("1:get patient name")
}
self.getId(path: "nurses", value: BookingTreatmentListController.nurseName) { snapshotKey in
BookingViewController.kardexDict["nurse"] = snapshotKey as AnyObject?
print("2:get nurse name")
}
Database.database().reference().child("kardexes").child(BookingViewController.newKardex.id).updateChildValues(BookingViewController.kardexDict)
print("save kardexDict")
}
我希望得到以下结果
"1:获取患者姓名"->在getId中运行"-> "2:获取护士姓名"->在getId中运行"->保存kardexDict"
"1:get patient name" -> "running in getId" -> "2:get nurse name" -> "running in getId" -> "save kardexDict"
但是我得到了
"1:获取患者姓名"->"2:获取护士姓名"->保存kardexDict"
But I got
"1:get patient name" -> "2:get nurse name" -> "save kardexDict"
并且kardexDict中的数据不正确,因为该数据不是从函数getId()获得的 我该怎么做才能迫使程序按照我的预期进行.
and the data in kardexDict is not correct since the data is not obtained from function getId() What can I do to force the program follow my order I expected.
推荐答案
您使用Firebase的方式错误:
You are using firebase in the wrong way:
-
observeSingleEvent
异步运行,因此事件的顺序为:在getId中运行"->"1:获取患者姓名" -
updateChildValues
通常会在任何observeSingleEvent
完成之前被调用
observeSingleEvent
runs asynchronously, so the order of events will be: "running in getId" -> "1:get patient name"updateChildValues
will typically called before any of theobserveSingleEvent
finishes
因此,在获得患者或护士姓名之前,您首先将空(?)kardexDict
写到firebase.
Hence, you first write the empty(?) kardexDict
to firebase, before you even get the patient or nurse name.
此外,请注意completion
闭包未在主线程中运行.因此,您可能会观察到一些不可预测的并发问题/竞态条件.
您要做的就是等待所有observeSingleEvent
完成,然后将数据写回.
Also, be aware the the completion
closure does not run in the main thread. Therefore, you will likely observe some unpredictable concurrency issues / race conditions.
What you have to do is, to wait for all observeSingleEvent
to be finished, and then write the data back.
因此,您的想法 或多或少会像这样(可能无法完全编译,因为我没有运行您的环境):
So, an more or less 1-to-1 transfer of your idea could look like this (might not exactly compile, because I don't have your environment running):
func getId(path:String, value:String?, completion: @escaping (String?) -> Void) {
let ref = Database.database().reference(withPath: path).queryOrdered(byChild: "name").queryEqual(toValue: value)
ref.observeSingleEvent(of: .childAdded, with: { snapshot in
print("running in getId")
completion(snapshot.key)
}) { (error) in
print(error.localizedDescription)
}
}
@objc func onTapConfirmed(){
let patientName = self.kardex?.patient?.name
let nurseName = BookingTreatmentListController.nurseName
self.getId(path: "patients", value: patientName) { snapshotKey in
print("1:got patient")
let patient = snapshotKey as AnyObject?
self.getId(path: "nurses", value: nurseName) { snapshotKey in
print("2:got nurse")
let nurse = snapshotKey as AnyObject?
DispatchQueue.Main.async {
print("save kardexDict (in main thread!")
BookingViewController.kardexDict["patient"] = patient
BookingViewController.kardexDict["nurses"] = nurse
let kardexes = Database.database().reference().child("kardexes")
kardexes.child(BookingViewController.newKardex.id).updateChildValues(BookingViewController.kardexDict)
}
}
}
}
尽管如此,它可能不是有效的,因为涉及到两个单独的网络呼叫(首先是患者,然后是护士).也许您最好使用observe
而不是observeSingleEvent
.
Nevertheless, it might not be that efficient, because there are two separate web calls involved (first the patients, then the nurses). Maybe you better use observe
instead of observeSingleEvent
.
这篇关于如何修复Firebase的异步问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!