javascript中两个函数之间的范围问题

时间:2019-12-28 14:59:06

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

我尝试使用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']

2 个答案:

答案 0 :(得分:2)

数据是从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)
      }
    }
}

最大的变化是:

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

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

答案 1 :(得分:0)

由于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)
          }
        });
}