在为下一个成员运行循环之前完成任务

菲利普·德根哈特(Filip Degenhart)

我为网站提供了以下简单且简短的javascript代码:

db.collection("classes").doc(data.readGrades).get().then(function(doc) {
          if (doc.exists) {
            const data = doc.data();
            const members = data.members;

            members.forEach(el => {

              db.collection("users").doc(el).collection("grades").get().then(function(querySnapshot) {
                querySnapshot.forEach(function(doc) {
                    const data = doc.data();

                    //some stuff

                });
              });
            })

          } else {
            console.log("No such document!");
          }
        }).catch(function(error) {
          console.log("Error getting document:", error);
        });  

如您所见,我需要运行两个Firebase Firestore任务。重要的是首先运行db.collection("classes").doc(data.readGrades).get().then(function(doc) {此任务,然后对每个成员执行此任务db.collection("users").doc(el).collection("grades").get().then(function(querySnapshot) {(注意:由于var,第二个任务需要第一个任务el)。所以我的问题是,在下一个成员的循环继续之前,我必须等待完成第二个任务。

而这恰恰是我的问题:在为下一个成员运行循环之前如何完成第二个任务?

编辑:
我这样修改了我的Javascript代码:

db.collection("classes").doc(data.readGrades).get().then(function(doc) {
    if (doc.exists) {
        const data = doc.data();
        const members = data.members;

        members.reduce((chain, el) => {

          table_number++;
          const html = fillTemplate("grade_table" + table_number, member_name);
          document.getElementById("main_padding").insertAdjacentHTML('beforeend', html);

            return chain.then(() =>
                db.collection("users").doc(el).collection("grades").get().then(function(querySnapshot) {
                    querySnapshot.forEach(function(doc) {
                        const data = doc.data();

                        addToTable("grade_table" + table_number, doc.id, data.mdl, data.klu);
                    });
                })
            )
        }, Promise.resolve());
    } else {
        console.log("No such document!");
    }
}).catch(function(error) {
    console.log("Error getting document:", error);
});

function fillTemplate(table_name, id) {
  console.log("ID OF TABLES  " + table_name);
  return `
  <div class="noten_tabelle_permission" id="noten_tabelle_permission">
    <h1 id="member_name">${id}</h1>
    <table id="${table_name}" style="width:100%">
      <tr>
        <th>Fach</th>
        <th>mündlich</th>
        <th>Klausur</th>
      </tr>
      <!-- Make content with js code -->
    </table>
  </div>
  `;
}

function addToTable(table_name, subject, mdl, klu) {

  var subject_name = getSubjectByNumber(subject);
  var short_subject = getSubjectShortByNumber(subject);

      //Zeile erstellen

      console.log("addToTable " + table_name);

      var y = document.createElement([short_subject]);
      y.setAttribute("id", [short_subject]);
      document.getElementById([table_name]).appendChild(y);

      //Spalten in einer Zeile

      var y = document.createElement("TR");
      y.setAttribute("id", [short_subject]);

      //Spalten in einer Zeile

      var cE = document.createElement("TD");
      var tE = document.createTextNode([subject_name]);
      cE.appendChild(tE);
      y.appendChild(cE);

      var a = document.createElement("TD");
      var b = document.createTextNode([mdl]);
      a.appendChild(b);
      y.appendChild(a);

      var c = document.createElement("TD");
      var d = document.createTextNode([klu]);
      c.appendChild(d);
      y.appendChild(c);


      document.getElementById(table_name).appendChild(y);
}

因此,诺言行得通。但是现在我有一个问题,就是诺言行不通。如您所见,我想为每个成员运行一个Firestore(Database)任务。因此,诺言应解雇每个新成员。但是,承诺最终将首先兑现。

背景知识:我从数据库的ArrayList中获取成员,对于每个成员,我需要基于该成员获取特定值。加载成员的值后,我将它们添加到表中,该表将填充上一个任务中的每个成员(如您所见)。正如我所说的,诺言最终将兑现。因此,这些值将不会添加到成员的特定表中。它们将被添加到最后一个表中。

编辑2:这是编辑的代码:

members.reduce((chain, el) => {

              db.collection("users").doc(el).collection("user_data").doc("u").get().then(function (doc) {
                const data = doc.data();
                var member_name = data.name;

                table_number++;
                const html = fillTemplate("grade_table" + table_number, member_name);
                document.getElementById("main_padding").insertAdjacentHTML('beforeend', html);
              })


          return chain.then(((table_num) => {
            return db.collection("users").doc(el).collection("grades").get().then(function (querySnapshot) {
              querySnapshot.forEach(function (doc) {
                const data = doc.data();

                addToTable("grade_table" + table_num, doc.id, data.mdl, data.klu);

              });
            })
          }).bind(null, table_number))
        }, Promise.resolve());

所以这里的问题是,我获得member_name的任务异步运行,而另一部分则不然。因此,只有在加载了所有内容后,我才能运行整个任务。因为如您所见,我还需要member_name。因此,如何重新编码,以便仅加载所有内容(member_name / grades)时任务运行。

安东库

您可以使用reduce而不是forEach将空Promise值作为初始值来传递,以便按顺序处理成员:

db.collection("classes").doc(data.readGrades).get().then(function(doc) {
    if (doc.exists) {
        const data = doc.data();
        const members = data.members;

        members.reduce((chain, el) => {
            return chain.then(() =>
                db.collection("users").doc(el).collection("grades").get().then(function(querySnapshot) {
                    querySnapshot.forEach(function(doc) {
                        const data = doc.data();
                        //some stuff
                    });
                })
            )
        }, Promise.resolve());
    } else {
        console.log("No such document!");
    }
}).catch(function(error) {
    console.log("Error getting document:", error);
});

更新#1

考虑到更新后的问题,数据可能会添加到最后一个表中,因为在答应解决期间,所有reduce迭代均已完成(因此,table_name变量保留了上次迭代的值)。您可以通过binding table_name对promise决议中调用的回调值来解决它

members.reduce((chain, el) => {

  table_number++;
  const html = fillTemplate("grade_table" + table_number, doc.id);
  document.getElementById("main_padding").insertAdjacentHTML('beforeend', html);

  return chain.then(((table_num) => {
    return db.collection("users").doc(el).collection("grades").get().then(function (querySnapshot) {
      querySnapshot.forEach(function (doc) {
        const data = doc.data();

        addToTable("grade_table" + table_num, doc.id, data.mdl, data.klu);
      });
    })
  }).bind(null, table_number))
}, Promise.resolve());

更新#2:为了随后在单个reduce迭代中运行多个异步操作,请尝试使用thenPromise方法将它们链接起来

members.reduce((chain, el) => {

  return chain
    .then(() => db.collection("users").doc(el).collection("user_data").doc("u").get())
    .then(doc => {
      const data = doc.data();
      var member_name = data.name;

      table_number++;
      const html = fillTemplate("grade_table" + table_number, member_name);
      document.getElementById("main_padding").insertAdjacentHTML('beforeend', html);
      return table_number;
    })
    .then(table_num => {
      return db.collection("users").doc(el).collection("grades").get().then(function (querySnapshot) {
        querySnapshot.forEach(function (doc) {
          const data = doc.data();

          addToTable("grade_table" + table_num, doc.id, data.mdl, data.klu);

        });
      })
    })

}, Promise.resolve());

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Python:下一个for循环

Java中的for循环在接收下一个输入之前运行3次

在继续执行下一个任务之前,使gulp同步写入文件

告诉waf等待任务完成,然后盯着下一个任务

开玩笑:在运行下一个测试之前,请等待异步测试完成

确保forEach循环在下一个命令js之前完成

在循环中执行下一个HTTP发布之前,请先完成HTTP发布请求

如何在Angular 6中的for循环中移至下一个索引之前等待完成订阅

为什么在ngUnsubscribe的“完成”之前“下一个”?

在运行下一个代码之前,如何等待异步JSZip .forEach()调用完成?

在循环移动到VBA中的下一个迭代之前,调用子未完成

Logstash-如果在下一个预定时间开始之前预定任务没有完成,会发生什么情况?

Java流在完成上一个之前开始下一个映射

C ++在继续下一个任务之前先完成当前任务

Alfresco:如何在下一个任务中查看完成任务的数据?

解析:在移至下一个任务之前先查询finsih任务

任务执行器不会立即运行下一个任务

jbpm 5.4任务已完成,但未创建下一个任务

在传递到下一个任务之前访问src参数的值

迭代循环的下一个迭代之前,请完成FOR LOOP内部的所有功能

等待循环中的每个动画完成,然后再运行下一个动画

在当前命令完成之前运行下一个命令

Retrofit2:在 recyclerview 中执行下一个任务之前等待响应

在为 Model Rails 创建对象之前获取下一个对象 ID

Sidekiq“默认”队列在第一个作业完成之前不会运行下一个作业

生成 ajax 调用的循环数组,我需要在下一个调用开始之前完成第一个调用

如何在执行下一个史诗之前确保完成一个史诗?

完成第一个任务后,如何使异步任务继续执行下一个任务?

在 nodejs 中开始下一个循环之前,等待每个 for 循环迭代完成