我有一系列键,这些键可以为我的社交网络发布对象,例如/ posts / id /(post info)
当我加载帖子时,我使用的observeSingleEventOfType(.Value)方法先加载/ posts / 0,然后加载/ posts / 1等。
observeSingleEventOfType(.Value)
我一次使用A lazyTableView加载30,速度非常慢。有什么方法可以使用一种查询方法,还是另一种可以使其更快的方法,即使我必须重组JSON树中的数据。
lazyTableView
我来自Parse,它重新实现了我的应用程序,到目前为止,体验非常好。只是这一件事我有点坚持。在此先感谢您的帮助!
编辑:
func loadNext(i: Int) { // check if exhists let ideaPostsRef = Firebase(url: "https://APPURL") ideaPostsRef.childByAppendingPath(i.description).observeSingleEventOfType(.Value, withBlock: { (snapshot) in if i % 29 == 0 && i != 0 && !self.hitNull { return } // false if nil // true if not nil if !(snapshot.value is NSNull) { let postJSON = snapshot.value as! [String: AnyObject] print("GOT VALID \(postJSON)") let post = IdeaPost(message: postJSON["message"] as! String, byUser: postJSON["user"] as! String, withId: i.description) post.upvotes = postJSON["upvotes"] as! Int self.ideaPostDataSource.append(post) self.loadNext(i + 1) } else { // doesn't exhist print("GOT NULL RETURNING AT \(i)") self.doneLoading = true self.hitNull = true return } } }
这个递归函数实际上是从Firebase获取键号i的值。如果它是NSNULL,它将知道这是最后一个可能要加载的帖子,并且不再执行。如果未击中NSNULL,但i % 29 == 0它作为基本情况返回,因此一次仅加载30个帖子(索引为0)。当我设置doneLoading为时true,tableView.reloadData()使用属性观察器调用。
i % 29 == 0
doneLoading
true
tableView.reloadData()
这是我正在获取的数组的示例
"ideaPosts" : [ { "id" : 0, "message" : "Test", "upvotes" : 1, "user" : "Anonymous" }, { "id" : 1, "message" : "Test2", "upvotes" : 1, "user" : "Anonymous" } ]
更新:现在,我们还在 AskFirebase情节中涵盖了这个问题。
从Firebase加载许多项目不必太慢,因为您可以通过管道传递请求。但是您的代码使这成为不可能,这确实会导致性能欠佳。
在代码中,您从服务器请求一个项目,等待该项目返回,然后加载下一个。在简化的序列图中,如下所示:
Your app Firebase Database -- request item 1 --> S L e o r a v d e i <- return item 1 -- r n g -- request item 2 --> S L e o r a v d e i r n <- return item 2 -- g -- request item 3 --> . . . -- request item 30--> S L e o r a v d e i r n g <- return item 30 --
在这种情况下,您正在等待30倍的往返时间+ 30倍的时间从磁盘加载数据。如果(为简单起见)我们说往返需要1秒,而从磁盘加载项目也要花费至少1秒,即30 *(1 + 1)= 60秒。
在Firebase应用程序中,如果一次性发送所有请求(或至少合理数量的请求),您将获得更好的性能:
Your app Firebase Database -- request item 1 --> -- request item 2 --> S L -- request item 3 --> e o . r a . v d . e i -- request item 30--> r n g <- return item 1 -- <- return item 2 -- <- return item 3 -- . . . <- return item 30 --
如果我们再次假设往返时间为1秒,加载时间为1秒,则您正在等待30 * 1 +1 = 31秒。
因此:所有请求都通过相同的连接。鉴于此,之间的唯一区别get(1),get(2),get(3)和getAll([1,2,3])一些开销帧。
get(1)
get(2)
get(3)
getAll([1,2,3])
我设置了一个jsbin来演示行为。数据模型非常简单,但是却显示出了差异。
function loadVideosSequential(videoIds) { if (videoIds.length > 0) { db.child('videos').child(videoIds[0]).once('value', snapshot => { if (videoIds.length > 1) { loadVideosSequential(videoIds.splice(1), callback) } }); } } function loadVideosParallel(videoIds) { Promise.all( videoIds.map(id => db.child('videos').child(id).once('value')) ); }
进行比较:在我的系统上顺序加载64个项目需要3.8秒,而以管道方式加载它们(如Firebase客户端本机一样)则需要600毫秒。确切的数字将取决于您的连接(延迟和带宽),但是流水线版本应始终明显更快。