我注意到如果我在Firebase中执行查询并且无法访问数据库服务器,则回调会一直等待(或直到服务器再次可访问)。
如果这种行为对于所使用的异步方法非常自然,那么有一种简单的方法可以指定超时,这样您就可以告知用户状态。
有没有这样的选择,我只是错过了 - 或者它真的丢失了? 或者您将如何解决这个问题?
答案 0 :(得分:3)
截至目前,这些听众没有超时概念。一种选择是自己管理超时。
当我还想在加载内容时显示进度对话框时,我就是这样做的。
private void showProgressDialog(boolean show, long time) {
try {
if (progressDialog != null) {
if (show) {
progressDialog.setMessage("Cargando...");
progressDialog.show();
new Handler().postDelayed(new Runnable() {
public void run() {
if(progressDialog!=null && progressDialog.isShowing()) {
progressDialog.dismiss();
Toast.makeText(ActPreguntas.this, "Couldn't connect, please try again later.", Toast.LENGTH_LONG).show();
}
}
}, time);
} else {
progressDialog.dismiss();
}
}
}catch(IllegalArgumentException e){
}catch(Exception e){
}
}
因此,当您向Firebase发出请求时,请调用showProgressDialog(true,5000),如果对话框仍然存在,则会在5秒后因为无法连接而导致您按照超时执行操作。
在Firebase侦听器的回调中,你执行showProgressDialog(false,0)
希望它有所帮助。
答案 1 :(得分:2)
你可以自己管理一个定时器控制器,在x秒后删除你的firebase引用的监听器。它非常简单,例如在android中只有一行代码。
您可以看到网络代码(Detaching Callbacks部分): https://www.firebase.com/docs/web/guide/retrieving-data.html
或用于android(Detaching Callbacks部分): https://www.firebase.com/docs/android/guide/retrieving-data.html#section-detaching
IOS的相同部分;)
答案 2 :(得分:0)
我建议只使用一个线程?
允许您自己从线程实例中分配对Firebase的调用,然后在极少数情况下,写入Firebase的时间太长 ,您可以取消线程吗?
let thread = NSThread(target:self, selector:#selector(uploadToFirebase), object:nil)
。 。
func uploadToFirebase(data: Dictionary) {
// Do what you need to here. Just an example
db.collection("posts").document("some unique post id").setData([
"name": "John",
"likes": 0
]) { err in
if let err = err {
print("Error writing document: \(err)")
} else {
print("Document successfully written!")
}
}
}
然后只创建一个计时器,如果该计时器触发则取消该线程。如果不是,只需取消计时器。
答案 3 :(得分:0)
如果您使用的是Firebase SDK v6.5.0及更高版本,则可以使用 FirebaseOptions的setConnectTimeout (https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/FirebaseOptions.Builder.html#setConnectTimeout(int))。
示例:
Integer connectTimeoutinMillis = 6000; //6 seconds
FirebaseOptions firebaseOptions = FirebaseOptions.builder()
.setCredentials(credentials)
.setDatabaseUrl(Application.firebaseSDKDatabaseUrl)
.setConnectTimeout(connectTimeoutinMillis)
.build();
FirebaseApp.initializeApp(firebaseOptions);
答案 4 :(得分:0)
这是我针对Firebase iOS SDK的解决方案,这可能对其他人有帮助:
extension DatabaseReference {
func observe(_ eventType: DataEventType, timeout: TimeInterval, with block: @escaping (DataSnapshot?) -> Void) -> UInt {
var handle: UInt!
let timer = Timer.scheduledTimer(withTimeInterval: timeout, repeats: false) { (_) in
self.removeObserver(withHandle: handle)
block(nil)
}
handle = observe(eventType) { (snapshot) in
timer.invalidate()
block(snapshot)
}
return handle
}
}
用法:
database.child("users").observe(.value, timeout: 30) { (snapshot) in
guard let snapshot = snapshot else {
// Timeout!
return
}
// We got data within the timeout, so do something with snapshot.value
}