【问题标题】:scope issue in javascript between two Functions两个函数之间的javascript范围问题
【发布时间】:2020-04-18 02:06:43
【问题描述】:

我尝试使用 xlsx-populate 获取 excel 表,因此我尝试从 mailEvents 集合中获取值,以便我可以在 init Collection 函数中添加或传递值。如果我已经解决了这个问题,那么我的问题与excel也解决了。 在这个问题中,我想访问 init 集合中的 topHeader var。 在 arr2 中有这种形式的值 ['open','processed']

const completeReport = (startTime,endTime) => {
    serverRef = db.collection("MailEvents");
    let getDocs = serverRef
      .where("timestamp", ">=", startTime)
      .where("timestamp", "<=", endTime)
      .get()
      .then(querySnapshot => {
        if (querySnapshot) {
          let docs = querySnapshot.docs.map(doc => doc.data());
          let arr1 = ["email", "reportName", "office"];
          let arr2 = docs.map(a => a.event);

          let topHeader = [...new Set(arr1.concat(arr2))];
        }
      });
      let query = db.collection("inits");
      let queryData = query
        .where("report", "in", ["payroll", "footprints"])

        .get()
        .then(querySnapshot => {
          if (querySnapshot) {
            let docs = querySnapshot.docs.map(doc => doc.data());
            console.log(topHeader)
          }
        });
}

所以我想要这种形式的输出

["email", "reportName", "office",'open','processed']

【问题讨论】:

  • 让有一个块范围。改为定义一个全局变量
  • 不是很全局,但是将 let 声明移动到第二行 serverRef = db.collection("MailEvents"); 行之前。将作业留在原处。
  • @JeremyJStarcher 你能解释一下吗

标签: javascript arrays google-cloud-firestore xlsx-populate


【解决方案1】:

数据是从 Firebase 异步加载的,因为它可能需要一些时间才能返回。您的主代码无需等待数据返回,而是继续立即执行。然后当数据可用时,使用该数据调用您的 then() 回调。

这意味着任何需要从 Firestore 访问数据的代码都必须在 then() 回调中,或者从那里调用。

例如:

const completeReport = (startTime,endTime) => {
    serverRef = db.collection("MailEvents");
    let getDocs = serverRef
      .where("timestamp", ">=", startTime)
      .where("timestamp", "<=", endTime)
      .get()
      .then(querySnapshot => {
        if (querySnapshot) {
          let docs = querySnapshot.docs.map(doc => doc.data());
          let arr1 = ["email", "reportName", "office"];
          let arr2 = docs.map(a => a.event);

          let topHeader = [...new Set(arr1.concat(arr2))];

          let query = db.collection("inits");
          let queryData = serverRef
            .where("report", "in", ["payroll", "footprints"])
            .get()
            .then(querySnapshot => {
              if (querySnapshot) {
                let docs = querySnapshot.docs.map(doc => doc.data());
                console.log(topHeader)
              }
            });
        }
      });
}

有一些替代方案,尤其是当您愿意使用更现代的 JavaScript 结构时。最简单的方法是使用 async / await 关键字,它将上面的内容包装在一些对大多数开发人员来说更正常的语法糖中。

当你申请async/await时,上面的代码会变成这样:

const completeReport = async (startTime,endTime) => {
    serverRef = db.collection("MailEvents");
    let querySnapshot = await serverRef
      .where("timestamp", ">=", startTime)
      .where("timestamp", "<=", endTime)
      .get();
    if (querySnapshot) {
      let docs = querySnapshot.docs.map(doc => doc.data());
      let arr1 = ["email", "reportName", "office"];
      let arr2 = docs.map(a => a.event);

      let topHeader = [...new Set(arr1.concat(arr2))];

      let query = db.collection("inits");
      querySnapshot = await serverRef
        .where("report", "in", ["payroll", "footprints"])
        .get();
      if (querySnapshot) {
        let docs = querySnapshot.docs.map(doc => doc.data());
        console.log(topHeader)
      }
    }
}

这里最大的变化是:

  • completeReport 函数上的 async 标记,因为调用者需要注意此函数现在可能会返回承诺/展示异步行为。
  • 两个 get() 调用中的 await 关键字,这意味着您不再需要 then 块。
  • 缩进减少,尤其是与我回答中的第一个 sn-p 相比时。

使用这种方法时要始终意识到的一件事是调用仍然是异步的。虽然使用 async / await 使代码更易于阅读,但它不会改变 API 的实际行为。

【讨论】:

    【解决方案2】:

    由于 let 有块作用域,它不能被外部访问。

    建议您使用var 声明一个变量,然后再分配它。

    希望这会有所帮助!

    const completeReport = () => {
        let serverRef = db.collection("MailEvents");
        var topHeader; 
        let getDocs = serverRef
          .where("timestamp", ">=", startTime)
          .where("timestamp", "<=", endTime)
          .get()
          .then(querySnapshot => {
            if (querySnapshot) {
              let docs = querySnapshot.docs.map(doc => doc.data());
              let arr1 = ["email", "reportName", "office"];
              let arr2 = docs.map(a => a.event);
    
              topHeader = [...new Set(arr1.concat(arr2))]; //assign value
            }
          });
          serverRef = db.collection("inits");
          let queryData = serverRef
            .where("report", "in", ["payroll", "footprints"])
    
            .get()
            .then(querySnapshot => {
              if (querySnapshot) {
                let docs = querySnapshot.docs.map(doc => doc.data());
                console.log(topHeader)
              }
            });
    }
    

    【讨论】:

    • 你需要letserverRef前面。
    • 打印未定义
    • @Amar - 我的代码中有一个错字 - 将 var topheader 更改为 topHeader。请交叉检查
    • @MonicaAcha 我已经在我的主代码中尝试过,但它不起作用它打印未定义
    • @Amar 你能发布控制台上显示的错误日志吗
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多