首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >通过使用查询而不是重复观察单个事件来加快我的社交网络应用获取帖子的速度

通过使用查询而不是重复观察单个事件来加快我的社交网络应用获取帖子的速度
EN

Stack Overflow用户
提问于 2016-03-11 11:11:32
回答 1查看 27K关注 0票数 106

我有一组键,这些键指向我的社交网络的post对象,比如so /post/id/(Post info)

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

我使用lazyTableView一次加载30个,它相当慢。有没有什么方法可以让我在JSON树中重构数据时也能使用其中一种查询方法或另一种方法来加快查询速度?

我来自Parse,重新实现了我的应用程序,到目前为止,体验相当不错。只有一件事让我有点纠结。提前感谢您的帮助!

编辑:

代码语言:javascript
复制
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,它知道这是最后一个可能加载的post,并且永远不会再次加载。如果NSNULL没有命中而是i % 29 == 0,那么它将作为基本情况返回,因此一次只加载30个帖子(索引为0)。当我将doneLoading设置为true时,将使用属性观察器调用tableView.reloadData()

下面是我正在获取的数组的样例

代码语言:javascript
复制
"ideaPosts" : [ {
    "id" : 0,
    "message" : "Test",
    "upvotes" : 1,
    "user" : "Anonymous"
  }, {
    "id" : 1,
    "message" : "Test2",
    "upvotes" : 1,
    "user" : "Anonymous"
  } ]
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-11 13:18:54

更新:我们现在也在中涵盖了这个问题。

从Firebase加载许多项并不是很慢,因为您可以通过管道传递请求。但是您的代码使这一切变得不可能,这确实会导致性能不佳。

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

代码语言:javascript
复制
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应用程序中,如果您一次性发送所有请求(或至少发送合理数量的请求),您将获得更好的性能:

代码语言:javascript
复制
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])之间的唯一区别就是帧的一些开销。

我设置了一个jsbin to demonstrate the behavior。数据模型非常简单,但它显示了不同之处。

代码语言:javascript
复制
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客户端本地做的那样)需要600ms。确切的数字将取决于您的连接(延迟和带宽),但流水线版本应该总是快得多。

票数 136
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35931526

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档