通过使用查询而不是重复观察单个事件,加快为我的社交networking应用程序提取post

我有一个键数组,导致我的社交networking,如so / posts / id /(发布信息)

当我加载post加载/post/ 0,然后/post/ 1等使用observeSingleEventOfType(.Value)方法。

我一次使用lazyTableView加载30,这是相当缓慢的。 有什么办法可以使用其中一种查询方法,或者使其更快的方法,即使我必须重构我的JSON树中的数据。

我来自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 } }) 

这个recursion函数本质上是从firebase获取关键字i的值。 如果它是NSNULL它知道这是最后一个可能的职位加载,永远不会再次。 如果NSNULL没有被击中,但是我%29 == 0然后它返回作为一个基本情况,所以一次只加载30个职位(0索引)。 当我将doneLoading设置为true时, tableView.reloadData()被使用属性观察器调用。

这里是我正在抓取的数组的样子

 "ideaPosts" : [ { "id" : 0, "message" : "Test", "upvotes" : 1, "user" : "Anonymous" }, { "id" : 1, "message" : "Test2", "upvotes" : 1, "user" : "Anonymous" } ] 

更新:我们现在也在AskFirebase插曲中讲述了这个问题。

从Firebase加载多个项目不一定很慢,因为您可以pipe理请求。 但是你的代码使这个不可能,这确实会导致性能不理想。

在您的代码中,您从服务器请求一个项目,等待该项目返回,然后加载下一个项目。 在一个简单的顺序图,看起来像:

 Your app Firebase Database -- request item 1 --> SL eo ra vd ei <- return item 1 -- rn g -- request item 2 --> SL eo ra vd ei rn <- return item 2 -- g -- request item 3 --> . . . -- request item 30--> SL eo ra vd ei rn g <- return item 30 -- 

在这种情况下,您需要等待30倍的往返时间+ 30倍从磁盘加载数据的时间。 如果(为了简单起见)我们说往返需要1秒钟,从磁盘加载一个项目也需要一秒钟,至less30 *(1 + 1)= 60秒。

在Firebase应用程序中,如果一次发送所有请求(或至less一个合理数量),您将获得更好的性能:

 Your app Firebase Database -- request item 1 --> -- request item 2 --> SL -- request item 3 --> eo . ra . vd . ei -- request item 30--> rn 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])之间的唯一区别是帧的开销。

我build立了一个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毫秒。 确切的数字将取决于您的连接(延迟和带宽),但stream水线版本应该总是快得多。