如何使用Firebase处理查询中的超时

如何使用Firebase处理查询中的超时,firebase,Firebase,我注意到,如果我在Firebase中执行查询,但无法访问数据库服务器,则回调将永远等待(或者直到再次访问服务器) 如果这种行为对于所使用的异步方法来说是很自然的,那么有一种简单的方法来指定超时是很有用的,这样您就可以将状态通知用户 是否有这样的选择,而我只是错过了它-或它真的错过了? 或者您将如何解决此问题?您可以自行管理一个计时器控制器,在x秒后将侦听器删除到您的firebase引用。它非常简单,例如android中只有一行代码 您可以看到web的代码(分离回调部分): 或者对于androi

我注意到,如果我在Firebase中执行查询,但无法访问数据库服务器,则回调将永远等待(或者直到再次访问服务器)

如果这种行为对于所使用的异步方法来说是很自然的,那么有一种简单的方法来指定超时是很有用的,这样您就可以将状态通知用户

是否有这样的选择,而我只是错过了它-或它真的错过了?
或者您将如何解决此问题?

您可以自行管理一个计时器控制器,在x秒后将侦听器删除到您的firebase引用。它非常简单,例如android中只有一行代码

您可以看到web的代码(分离回调部分):

或者对于android(分离回调部分):


IOS的相同部分;)

今天,这些侦听器没有超时概念。一种选择是自己管理超时

这是我在加载内容的同时还希望显示进度对话框时的操作方式

    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)


希望有帮助。

我建议只使用线程

允许您自己从线程实例中分配对Firebase的调用,然后在写入Firebase花费太长的罕见情况下,您可以取消该线程吗

let thread = NSThread(target:self, selector:#selector(uploadToFirebase), object:nil)


然后只要创建一个计时器,如果计时器触发,它就会取消线程。如果不是,只需取消计时器

如果您使用的是Firebase SDK v6.5.0及更高版本,则可以使用FirebaseOptions的setConnectTimeout()

样本:

Integer connectTimeoutinMillis = 6000; //6 seconds
FirebaseOptions firebaseOptions = FirebaseOptions.builder()
 .setCredentials(credentials)
 .setDatabaseUrl(Application.firebaseSDKDatabaseUrl)
 .setConnectTimeout(connectTimeoutinMillis)
 .build();
FirebaseApp.initializeApp(firebaseOptions);

以下是我针对Firebase iOS SDK的解决方案,这可能对其他人有所帮助:

扩展数据库引用{
func observe(eventType:DataEventType,timeout:TimeInterval,带块:@escaping(DataSnapshot?->Void)->UInt{
变量句柄:UInt!
让timer=timer.scheduledTimer(withTimeInterval:timeout,repeats:false){(u)in
self.removeObserver(带句柄:句柄)
区块(无)
}
handle=observe(eventType){(snapshot)in
timer.invalidate()
块(快照)
}
返回手柄
}
}
用法:

database.child(“用户”).observe(.value,timeout:30){(快照)在
guard let snapshot=snapshot else{
//暂停!
返回
}
//我们在超时时间内获得了数据,因此请使用snapshot.value执行一些操作
}

如果您试图检测用户是否连接到Firebase服务器,请查看。也面临同样的问题。最后,在查询周围放置计时器,将其标记为timedout。使用Boltz framework for Maintenance tasks(BFTask),整个过程很容易完成,特别是在处理多个查询的情况下。observeSingleEventOfType,使用它我们无法获得句柄,因此无法分离回调。完成五秒钟后移除侦听器不是更好吗?或者,我们可以将超时功能烘焙到请求本身中,而不是将其绑定到UI组件。文档说明:“此设置不会影响FirebaseDatabase和FirestoreClient API。”iOS似乎也没有等效的选项。
Integer connectTimeoutinMillis = 6000; //6 seconds
FirebaseOptions firebaseOptions = FirebaseOptions.builder()
 .setCredentials(credentials)
 .setDatabaseUrl(Application.firebaseSDKDatabaseUrl)
 .setConnectTimeout(connectTimeoutinMillis)
 .build();
FirebaseApp.initializeApp(firebaseOptions);