Javascript 将两个以上的收藏从firestore复制到另一个收藏不会';行不通

Javascript 将两个以上的收藏从firestore复制到另一个收藏不会';行不通,javascript,reactjs,firebase,google-cloud-firestore,Javascript,Reactjs,Firebase,Google Cloud Firestore,因此,我的firestore数据库中有四个集合: 英语问题 数学问题 科学问题 宗可汗问题 我试图复制这些集合中的所有数据,并将其放在每个用户的一个集合中。所以看起来是这样的 用户名(集合) 数学问题(文档)-问题(集合) 英语问题(doc)-问题(集合) 科学问题(doc)-问题(集合) Dzongkha问题(文档)-问题(收集) 然而,当我尝试这样做时,它的行为很奇怪,因为有时候,所有四个集合都会被复制到username集合中,而其他时候只有前两个集合或第一个集合被复制 在我之前,你会

因此,我的firestore数据库中有四个集合:

  • 英语问题
  • 数学问题
  • 科学问题
  • 宗可汗问题
  • 我试图复制这些集合中的所有数据,并将其放在每个用户的一个集合中。所以看起来是这样的

  • 用户名(集合)
    • 数学问题(文档)-问题(集合)
    • 英语问题(doc)-问题(集合)
    • 科学问题(doc)-问题(集合)
    • Dzongkha问题(文档)-问题(收集) 然而,当我尝试这样做时,它的行为很奇怪,因为有时候,所有四个集合都会被复制到username集合中,而其他时候只有前两个集合或第一个集合被复制
  • 在我之前,你会一个接一个地调用每个集合的数据库。由于这不起作用,我试图使每个调用都成为它自己的函数,如下所示。不幸的是,这不起作用。任何帮助都将不胜感激

    接受@ralemos的建议后,它仍然不起作用,但新代码如下所示

        fire
          .auth()
          .createUserWithEmailAndPassword(this.state.email, this.state.password)
          .then((u) => {
            let user = fire.auth().currentUser;
            console.log(user);
            if (user != null) {
              user
                .updateProfile({
                  displayName: this.state.name,
                })
                .then((r) => {
                  let db = fire.firestore();
                  let data = {
                    name: this.state.name,
                    email: this.state.email,
                    college: this.state.college,
                    dzongkhag: this.state.dzongkhag,
                  };
                  db.collection(this.state.email).doc("UserProfile").set(data);
                  this.copyMathDatabase();
                });
            }
          });
      }
      copyMathDatabase() {
        let db = fire.firestore();
        db.collection("Questions")
          .get()
          .then((snapshot) => {
            snapshot.forEach((doc) => {
              db.collection(this.state.email).doc("MathQuestions").collection("Questions").doc(doc.id).set({
                Category: doc.data().Category,
                Choice: doc.data().Choice,
                CorrectAnswer: doc.data().CorrectAnswer,
                IsCorrectAnswer: doc.data().IsCorrectAnswer,
                IsWrongAnswer: doc.data().IsWrongAnswer,
                Question: doc.data().Question,
                UserHasNotResponded: doc.data().UserHasNotResponded,
                Marked: doc.data().Marked,
              });
              console.log("Math Questions: ", doc.id);
            });
            this.copyEnglishDatabase();
            console.log(" Done copying the Math database ");
          });
      }
    
      copyEnglishDatabase() {
        let db = fire.firestore();
        db.collection("EnglishQuestions")
          .get()
          .then((snapshot) => {
            snapshot.forEach((doc) => {
              db.collection(this.state.email).doc("EnglishQuestions").collection("Questions").doc(doc.id).set({
                Category: doc.data().Category,
                Choice: doc.data().Choice,
                CorrectAnswer: doc.data().CorrectAnswer,
                IsCorrectAnswer: doc.data().IsCorrectAnswer,
                IsWrongAnswer: doc.data().IsWrongAnswer,
                Question: doc.data().Question,
                UserHasNotResponded: doc.data().UserHasNotResponded,
                Marked: doc.data().Marked,
                Passage: doc.data().Passage,
                isPassageQuestion: doc.data().isPassageQuestion,
              });
              console.log("English Questions: ", doc.id);
            });
           
            console.log("Done copying the English database");
          });
      }
    

    这很可能是调用
    copyMathDatabase()
    copyEnglishDatabase()
    (两者都是异步的)导致的同步性问题,请依次尝试将代码块更改为以下内容:

    db.collection(this.state.email).doc("UserProfile").set(data).then(() =>{
        this.copyMathDatabase().then(() => {
            this.copyEnglishDatabase();
        });
    });
    
    copyMathDatabase() {
        let db = fire.firestore();
        return db.collection("Questions")
        ...
    }
    
    copyEnglishDatabase() {
        let db = fire.firestore();
        return db.collection("EnglishQuestions")
        ...
    }
    

    通过这种方式,您可以强制以正确的顺序执行代码并减少错误,这应该可以解决您面临的问题。

    请记住,许多/大多数Firestore调用都会返回一个承诺-这意味着操作的结果将在以后返回,可能要晚很多。只是一个接一个地打电话并不意味着一个人会等另一个——这根本不是承诺所能做的。您可能已经看到一些使用async/await的代码,它们看起来像是在等待对方,但只是“语法糖”(即使其看起来很好)隐藏了这样一个事实,即在“幕后”仍然有承诺

    以您为例,我将执行以下操作:

    db.collection(this.state.email).doc("UserProfile").set(data).then(() =>{
        this.copyMathDatabase().then(() => {
            this.copyEnglishDatabase();
        });
    });
    
    copyMathDatabase() {
        let db = fire.firestore();
        return db.collection("Questions")
        ...
    }
    
    copyEnglishDatabase() {
        let db = fire.firestore();
        return db.collection("EnglishQuestions")
        ...
    }
    
    请注意“return”-每个函数现在都返回一个结果的承诺,这将在稍后发生。然后,在身份验证功能区域中:

      fire
          .auth()
          .createUserWithEmailAndPassword(this.state.email, this.state.password)
          .then((u) => {
            let user = fire.auth().currentUser;
            console.log(user);
            if (user != null) {
              user
                .updateProfile({
                  displayName: this.state.name,
                })
                .then((r) => {
                  let db = fire.firestore();
                  let data = {
                    name: this.state.name,
                    email: this.state.email,
                    college: this.state.college,
                    dzongkhag: this.state.dzongkhag,
                  };
                  return db.collection(this.state.email).doc("UserProfile").set(data);
                })
                .then(() => {
                  return this.copyMathDatabase();
                 })
                .then(() => {
                  return this.copyEnglishDatabase();
                };
            }
          });
      }
    
    注意,.set()的结果返回一个承诺,该承诺将在完成时完成。然后()等待该承诺,然后执行copyMathDatabase(),它将在完成时返回一个要完成的承诺。然后()等待该承诺,然后执行copyEnglishDatabase(),该数据库在完成时返回一个要完成的承诺


    这个问题表明您对承诺的确切含义知之甚少,而这种理解对于使用Firestore是绝对关键和必要的。在你继续之前,你需要去教自己详细的承诺。您还应该了解什么是aync/await语法,以及它的实际功能。这里不是您学习这些东西的地方。

    您的代码表明,此时您只想复制前两个集合:
    js This.copyMathDatabase();这个.copyEnglishDatabase()@JayCodist我删除了另外两个调用,因为我只想尝试两个。如果我只调用一个集合,它就可以工作,但只要我尝试复制两个集合,它就会表现得很奇怪。它有时复制,有时不复制。由于这两个复制例程都是异步的,您是否在顶层存在之前检查它们的完成情况(尤其是写入情况)?是的,我更改了代码,现在它强制一个在另一个可以启动之前完成,但仍然无法工作@我们可以看看你是怎么修改密码的吗?对我们来说,仅仅凭猜测提供帮助是相当困难的……我试过了,但仍然不起作用。知道为什么吗?非常感谢你的帮助。您给出的方法也部分有效。每样东西都很好用,有时所有的收藏品都被完美地复制了。但有时,只有math集合被复制,而其他集合没有被复制。有什么想法吗?什么都没有。你没有给我们任何东西看。我们应该猜猜吗?