首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用防火墙onSnapshot在链中使用JavaScript?

如何使用防火墙onSnapshot在链中使用JavaScript?
EN

Stack Overflow用户
提问于 2020-08-25 15:49:56
回答 1查看 478关注 0票数 1

我想顺序地使用firebase的onSnapshot函数。下面给出了我想应用此方法的情况。

设想情况:

在消防局有两个藏品。EmployeesProjects.在Employees集合中,文档存储员工的详细信息。它还存储特定员工工作的Projects文档的it。在Projects集合中,存储项目的详细信息。

目标:

首先,我必须从与特定员工相关的Employees集合中获取数据。然后,从获取的雇员数据中,我将获得他/她正在处理的项目ID。因此,我需要从这个ID中获取项目的详细信息。因此,当任何与项目或员工相关的信息发生变化时,屏幕上的数据也应实时更改。

问题:

我试着写一段嵌套的代码。但它只对员工数据起实时作用。在更新项目详细信息时,它不会改变。就像这样..。

代码语言:javascript
运行
复制
admin.auth().onAuthStateChanged(async () => {
    if (check_field(admin.auth().currentUser)) {
        await db.collection('Employees').doc(admin.auth().currentUser.uid).onSnapshot(snap => {
            ...
            let project_details = new Promise(resolve => {
                let projects = [];
                for (let i in snap.data().projects_list) {
                    db.collection('Projects').doc(snap.data().projects_list[i]).onSnapshot(prj_snap => {
                        let obj = prj_snap.data();
                        obj['doc_id'] = prj_snap.id;
                        projects.push(obj);
                    });
                }
                resolve(projects);
            });

            Promise.all([project_details]).then(items => {
                ...
                // UI updation
            });
            ...
        });
    }
});

做这个的正确方法是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-25 16:32:11

实际上,您提出了一个非常复杂的数据流场景。我认为这是一个多步骤的问题。你的目标基本上是:

如果有用户,则实时侦听该用户的项目id列表。对于每个项目id,实时侦听有关project.

  • (presumably)清除不再相关的侦听器的详细信息。

所以我会处理这样的问题:

代码语言:javascript
运行
复制
let uid;
let employeeUnsub;
let projectIds = [];
let projectUnsubs = {};
let projectData = {};

const employeesRef = firebase.firestore().collection('Employees');
const projectsRef = firebase.firestore().collection('Projects');

firebase.auth().onAuthStateChanged(user => {
  // if there is already a listener but the user signs out or changes, unsubscribe
  if (employeeUnsub && (!user || user.uid !== uid)) {
    employeeUnsub();
  }

  if (user) {
    uid = user.uid;
    // subscribe to the employee data and trigger a listener update on changes
    employeeUnsub = employeesRef.doc(uid).onSnapshot(snap => {
      projectIds = snap.get('projects_list');
      updateProjectListeners();
    });
  }
});

function updateProjectListeners() {
  // get a list of existing projects being listened already
  let existingListeners = Object.keys(projectUnsubs);
  for (const pid of existingListeners) {
    // unsubscribe and remove the listener/data if no longer in the list
    if (!projectIds.includes(pid)) {
      projectUnsubs[pid]();
      delete projectUnsubs[pid];
      delete projectData[pid];
      render();
    }
  }

  for (const pid of projectIds) {
    // if we're already listening, nothing to do so skip ahead
    if (projectUnsubs[pid]) { continue; }
    // subscribe to project data and trigger a render on change
    projectUnsubs[pid] = projectsRef.doc(pid).onSnapshot(snap => {
      projectData[pid] = snap.data);
      render();
    });
  }
}

function render() {
  const out = "<ul>\n";
  for (const pid of projectIds) {
    if (!projectData[pid]) {
      out += `<li class="loading">Loading...</li>\n`;
    } else {
      const project = projectData[pid];
      out += `<li>${project.name}</li>`;
    }
  }
  out += "</ul>\n";
}

上面的代码实现了您所说的内容(在本例中,render()函数只返回一个字符串,但您可以在那里执行任何操作DOM / display数据的操作)。

这是一个很长的例子,但您正在讨论的是一个非常复杂的概念,即在实时数据发生变化时动态地加入它。希望这能给你一些前进方向的指导!

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

https://stackoverflow.com/questions/63582617

复制
相关文章

相似问题

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