Firebase实时数据库-基于访问节点设置多个.on()侦听器

时间:2020-11-07 14:35:37

标签: javascript firebase firebase-realtime-database nosql

我正在使用具有以下结构的Firebase实时数据库。 我希望获取用户有权访问并订阅这些笔记中的更改的所有“笔记”。

notes: {
  "noteId-1345" : {
    "access" : {
      "author": "1234567890"
        "members": {
          "1234567890": 0 <--- Author
          "0987654321": 1 <--- Member
        }
      },
    "data" : {
      "title": "Hello",
      "content": "Konichiwa!",
      "comment": "123"
    }
  }
}

(我知道,理想情况下,该结构可以更平坦。:))

要获取用户有权访问的所有笔记-我在根目录中保留一个附加的user_notes节点: 每当我将用户(更新members)与笔记相关联时,我都会同时更新/notes/$noteid/user_notes/$uid

user_notes: {
  "$uid": {
    "noteId-1345": {
      myHide: false,
      mySortOrder: 0,
      title: "Hello"
    }
  }
}

获取数据时,我希望为用户有权访问的所有笔记设置订阅。

我首先获取用户有权访问的笔记的ID,然后在每个note中附加侦听器以订阅更新。

const uid = getState().auth.uid
let collectedNotes = {} 
...
database.ref(`user_notes/${uid}`).on('value', (myAccessSnaps) => {
  myAccessSnaps.forEach((accessSnap) => {
    const noteId = accessSnap.key
    const privateData = {'personalData': {...accessSnap.val()}}
    database.ref(`notes/${noteId}`).on('value', (noteSnap)=>{
      const notData = noteSnap.val()
      const fullData = { ...privateData, ...notData }
      const note = {
        id: noteSnap.key,
        ...fullData
      }
      collectedNotes[note.id] = note
      ...
    })
  }))
})

(当然,在设置新的监听器之前,我将需要使用.off()来分离监听器)

这有点问题,因为我必须为每个note附加一个侦听器-数据库中可能有数百个注释。 这是最有效的方法吗? -效率低下。

是否可以通过一个监听器来监听用户在/notes路径中需要听的 ALL 笔记?还是我的做法完全错误? :)

亲切的问候/ K

1 个答案:

答案 0 :(得分:0)

了解了.on() does not return a promise后,我变得更容易解决问题了。

增加很多.on()听众对我来说毫无意义。

对我来说,最简单的方法是:

1-每次更新笔记时,都使用时间戳记updatedAt更新我的访问节点

2-使用返回承诺的.once()加载初始数据,请参见下面的代码。

3-为访问节点更改设置单独的订阅

let myPromises = []
database.ref(`user_notes/${uid}`).once('value', (myAccessSnaps) => {
  myAccessSnaps.forEach((accessSnap) => {
    const noteId = accessSnap.key
    const privateData = {'personalData': {...accessSnap.val()}}
    myPromises.push(
      database.ref(`notes/${noteId}`).once('value', (noteSnap)=>{
        const notData = noteSnap.val()
        const fullData = { ...privateData, ...notData }
        const note = {
          id: noteSnap.key,
          ...fullData
        }
        collectedNotes[note.id] = note
        ...
      })
    )
  }))
})

return Promise.all(myPromises)
.then(() => {
  dispatch(setNotes(categories))
...
// Set up subscription after initial load
database.ref(`user_notes/${uid}`).on('value', (myAccessSnaps) => {
  ...
  // Use access node listener only - gets updated by 'updatedAt'
  database.ref(`notes/${noteId}`).once('value', (noteSnap)=>{
    //Collect and dispatch data

亲切的问候/ K