scope issue in javascript between two Functions

允我心安 提交于 2021-02-08 06:33:10

问题


i have try to get the excel sheet using xlsx-populate so i am trying to get the values from mailEvents collections so i can add or pass the value in the init Collection function.if i have solved this issue then my problem regarding excel is also solved. in this problem i want to access the topHeader var in init collection. here in arr2 there is the values in this form ['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)
          }
        });
}

so i want the output in this form

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

回答1:


Data is loaded from Firebase asynchronously, since it may take some time to return. Instead of waiting for the data to return, your main code continues to execute straight away. Then when the data is available, your then() callback is called with that data.

This means that any code that needs access to the data from Firestore must be inside the then() callback, or be called from there.

For example:

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

There are some alternatives, especially when you're willing to use more modern JavaScript constructs. The simplest approach is to use the async / await keywords, which wrap the above in some nice syntactic sugar that reads more normal for most developers.

The above code would become this when you apply 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)
      }
    }
}

The biggest changes here are:

  • The async marker on the completeReport function, since the caller needs to be aware that this function may now return a promise/exhibit async behavior.
  • The await keywords on the two get() calls, which mean you don't need a then block anymore.
  • The reduced indentation, especially when compared to the first snippet in my answer.

One of the things to always realize when using this approach is that the calls are still asynchronous. While the use of async / await makes the code easier to read, it doesn't change the actual behavior of the APIs.




回答2:


Since let has block scope it wont be accessible outside.

Would recommend you to declare a variable with var and just assign it later.

Hope this helps!

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


来源:https://stackoverflow.com/questions/59511999/scope-issue-in-javascript-between-two-functions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!