Firebase:等待多个查询完成

时间:2018-04-15 08:52:14

标签: ios swift firebase

我有多个对不同Firebase数据库位置的引用,它们都获取了一些数据。在继续处理该数据的下一步之前,我需要收集所有数据。代码如下:

var webpack = require('webpack')
var path = require('path')
var extractTextPlugin = require('extract-text-webpack-plugin')
require("babel-polyfill")

module.exports = {
  entry: [
    'babel-polyfill', path.resolve(__dirname, 'src', 'index.js')
  ],
  resolve: {
    extensions: ['*', '.js', '.jsx']
  },
  output: {
    path: path.resolve(__dirname, '..', 'xxx', 'static', 'js'),
    publicPath: '../xxx/static/js',
    filename: 'xxx.js'
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader', 'eslint-loader']
      },
      {
        test: /\.(sass|scss)$/,
        loader: extractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'sass-loader']
        })
      }
    ]
  },
  plugins: [
    new extractTextPlugin({
      filename: '../xxx/static/css/xxx.css',
      allChunks: true
    }),
    new webpack.optimize.UglifyJsPlugin({
      minimize: true,
      compress: {
        warnings: false
      }
    }),
    new webpack.optimize.AggressiveMergingPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    })
  ]
}

我希望堆包含从这些查询中提取的所有帖子,然后在表视图中显示它们(因为时间戳排序)。有没有办法在继续之前等待上面的多个查询完成?

修改:由于我需要从Firebase的不同节点获取数据,因此我不能只进行一次查询调用。

3 个答案:

答案 0 :(得分:3)

您可以利用DispatchGroup等待其他查询完成。

稍微调整一下你的代码:

let group = DispatchGroup()
let dispatchQueue = DispatchQueue.global(qos: .userInitiated)

dispatchQueue.async(group: group,
                      qos: .userInitiated,
                    flags: DispatchWorkItemFlags.assignCurrentContext,
                  execute: {
    for ref in baseRefs {
        group.enter() // Enter the group for each reference.

        ref.queryOrdered... with: { (postRefs) in {
            ....
            self.postsHeap.enqueue(dummyPost)

            group.leave() // Leave the group after finishing.
        }
    }
}

group.notify(queue: .main) {                
    // Every ref has finished, continue from here.
}

答案 1 :(得分:1)

有很多方法可以实现这一目标,但Firebase以不同的数据库位置需要多个观察者来获取一个目的所需的数据来构建数据是不好的做法。

你提到帖子,所以我假设你正在创建某种类型的提要。

因此,不是从数据库的不同部分获取所有帖子并在客户端上组合/排序它们,而是每个用户都有一个Feed节点,当保存帖子时,您还会在用户Feed中保存该帖子的ID然后,您的查询只是用户的Feed节点上的一个观察者,该节点已经拥有您需要的所有内容。

此外,我可以看到您按日期排序',您是否知道Firebase ID按时间排序,因此您可以按其他子项排序(如果需要)orderByKey并限制为最后4,然后您可以获取最近的4个帖子,同时也询问其他孩子。

您可以使用多路径更新或云功能在数据库中复制(非规范化)数据。如果你来自SQL,这可能会让人觉得很奇怪,但与Firebase一样正常。

Here是一个firebase博客,其中包含有关正确结构的更多信息以及对数据进行非规范化。

答案 2 :(得分:1)

因为您知道有多少引用,并且您只想在处理最后一个引用时对UI进行排序和更新,所以如何使用简单的..if ..语句来查看是否已返回最后一个引用。像这样:

let lastRefIndex = baseRefs.count - 1 //the index of the last ref
for (index, ref) in baseRefs.enumerated { //index tracks which ref we are on
     ref.queryOrdered(byChild: "datetime").queryLimited(toFirst: 4)
        .observeSingleEvent(of: .value, with: { (postRefs) in
          for postRef in postRefs.children {
               let snapshotValue = ...
               let dummyPost = ...
               self.postsHeap.enqueue(dummyPost)
          }

          //the following code will execute once for each ref as the data becomes
          //  valid. So index will only equal the lastRefIndex when all of the
          //  data has been returned.
          if index == lastRefIndex { 
             self.postsHeap.sort()
             updateUI
          }
     })
}