Firebase 延迟加载

Firebase lazy load

我正在尝试延迟加载 firebase 项目,以便稍后在用户到达 div 容器末尾时加载更多项目。当我删除 .endAt().startAt() 时,我收到了 15 个项目,尽管它们没有增加并且卡在这 15 个项目上。

当我保持 .endAt().startAt() 时,我收到了 firebase 警告 Using an unspecified index. Consider adding ".indexOn": "title" at /items 即使设置了 .indexOn。我对那个警告感到困惑。在此先感谢您的帮助。

Firebase 结构

{
  "items" : {
    "-Kk6aHXIyR15XiYh65Ht" : {
      "author" : "joe", 
      "title" : "Product 1"
    },
    "-Kk6aMQlh6_E3CJt_Pnq" : {
      "author" : "joe",
      "title" : "Product 2"
    }
  },
  "users" : {
    "RG9JSm8cUndpjMfZiN6c657DMIt2" : {
      "items" : {
        "-Kk6aHZs5xyOWM2fHiPV" : "-Kk6aHXIyR15XiYh65Ht",
        "-Kk6aMTJiLSF-RB3CZ-2" : "-Kk6aMQkw5bLQst81ft7"
      },
      "uid" : "RG9JSm8cUndpjMfZiN6c657DMIt2",
      "username" : "joe"
    }
  }
}

安全规则

{
  "rules": {
    ".read": true,  
    ".write": "auth != null",  
    "users":{
      "$uid": {
        ".write": "$uid === auth.uid"
        "items":{
          ".indexOn": "title",
          "$itemId": {
            "title": {".validate": "...}
            "type": {".validate": "...}
            }
          }
        }
      }
    }
  }
}

延迟加载的代码结构

let _start = 0,
    _end = 14,
    _n = 15;

function lazyLoadItems(){
  firebase.database().ref('items')
        .orderByChild('title')
        .startAt(_start)
        .endAt(_end)
        .limitToFirst(_n)
        .on("child_added", snapshot=> console.log(snapshot.val()));
  _start += _n;
  _end += _n;
}

您误解了 Firebase 查询的工作原理。如果使用 hard-coded 值最容易查看:

firebase.database().ref('items')
    .orderByChild('title')
    .startAt(0)
    .endAt(14)
    .limitToFirst(15)

没有包含 title=0title=14 的项目,因此查询不匹配任何内容。

Firebase 数据库查询匹配您订购的 属性 的值。因此,当您按 title 排序时,您在 startAtendAt 中指定的值必须是标题。例如

ref.child('items')
   .orderByChild('title')
   .startAt("Product 1")
   .endAt("Product 1")
   .limitToFirst(15)
   .on("child_added", function(snapshot) { console.log(snapshot.val()); });

请参阅此工作示例:http://jsbin.com/hamezu/edit?js,console

要实现分页,您必须记住上一页的最后一项并将其传递给下一个调用:startAt(titleOfLastItemOnPreviousPage, keyOfLastItemOnPreviousPage).

startAfter 是最后一个元素

每次你必须发送最后一个元素:

const lastAlert = querySnapshot.docs[querySnapshot.docs.length - 1]

这里有一个例子:

export const fetchAlerts = (createdForId, startAfter) => {
  return new Promise((resolve, reject) => {
    firebase
    let query = firebase
      .firestore()
      .collection('alerts')
      .where('generated_for.uid', '==', createdForId)
      .where('read', '==', false)
      .orderBy('created_at', 'desc')
      .limit(25)
    if (startAfter) {
      query = query.startAfter(startAfter)
    }

    query
      .get()
      .then(querySnapshot => {
        const lastAlert = querySnapshot.docs[querySnapshot.docs.length - 1]
        const alerts = querySnapshot.docs.map(doc => ({
          ...doc.data(),
          uid: doc.id,
        }))
        resolve(alerts)
        resolve({ alerts, lastAlert })
      })
      .catch(error => {
        console.log(error.message)