首页 > 解决方案 > 在从 Firebase 收集数据之前呈现网页 - NodeJS 和 EJS

问题描述

我尝试过使用 async-await、.then 和 now promise。我是javascript开发的新手。

编码

indexRouter.get('/dashboard', checkSignIn, async(request, response) => {
    snapshot = await db.doc('users/accounts').get()
    sites = snapshot.data()['sites']
    const userId = request.session.userId
    snapshot = await db.doc(`users/${userId}`).get()
    var linkedSites = snapshot.data()['linked sites']
    let getDs = new Promise((resolve,reject)=>{
        console.log("1")
            linkedSites.forEach((site) =>{
                console.log("2")
            db.doc(`users/${userId}`).collection(site).get()
            .then((snapshot)=>{
                console.log("3")
                snapshot.forEach((doc) => {
                console.log("4")
                console.log(doc.id)
                emailId = doc.id
                keys = doc.data()['keys']
                var passwordEncrypt = doc.data()['password']
                password = cryptoJS.....
                details.push({site:{'email': emailId, 'password': password, 'keys': keys}})
                })
            })
        })
        console.log("5")
        console.log(details)
        resolve(details)
        }

    );

    getDs.then((details)=>{
        console.log("rendering")
        response.render('dashboard', {'details':details, 'linkedSites': linkedSites, 'sites': sites})
    })
}

我收到了回复

1
2
2
5
[]
rendering
error: ...details not found in ejs
3
4
rsp121@gmail.com
3
4
test@gmail.com

根据输出,console.log(2) 之后的 db.doc 行似乎在一段时间后被执行,并且之前发送了 resolve(details)。


找到了解决问题的方法:

indexRouter.get('/dashboard', checkSignIn, async(request, response) => {
    snapshot = await db.doc('users/accounts').get()
    sites = snapshot.data()['sites']
    const userId = request.session.userId
    snapshot = await db.doc(`users/${userId}`).get()
    var linkedSites = snapshot.data()['linked sites']
    if(linkedSites){
        const getSnapshot = (site) => {
            return new Promise(resolve => {
                db.doc(`users/${userId}`).collection(site).get()
                .then((snapshot) =>{
                    snapshot.forEach((doc) =>{
                        emailId = doc.id
                        keys = doc.data()['keys']
                        var passwordEncrypt = doc.data()['password']
                        password = cryptoJS
                        details[site] = {'email': emailId, 'password': password, 'keys': keys}
                        resolve(true)
                    })
                })
            })
        }

        Promise.all(linkedSites.map(getSnapshot)).then(()=>{
            console.log(linkedSites)
            response.set('Cache-Control', 'no-store, no-cache, must-revalidate, private')
            response.render('dashboard', {'details':details, 'linkedSites': linkedSites, 'sites': sites})
        })
    }

标签: javascriptnode.jsfirebasepromisegoogle-cloud-firestore

解决方案


问题是您的承诺在解决之前db.doc解决,并且您的 db.doc 承诺在循环中。所以,你应该使用promise.all 下面的代码应该适合你。

indexRouter.get("/dashboard", checkSignIn, async (request, response) => {
  snapshot = await db.doc("users/accounts").get();
  sites = snapshot.data()["sites"];
  const userId = request.session.userId;
  snapshot = await db.doc(`users/${userId}`).get();
  var linkedSites = snapshot.data()["linked sites"];
  let getDs = new Promise((resolve, reject) => {
    const promises = [];
    console.log("1");
    linkedSites.forEach((site) => {
      console.log("2");
      promises.push(
        new Promise((internalResolve) => {
          db.doc(`users/${userId}`)
            .collection(site)
            .get()
            .then((snapshot) => {
              console.log("3");
              snapshot.forEach((doc) => {
                console.log("4");
                console.log(doc.id);
                emailId = doc.id;
                keys = doc.data()["keys"];
                var passwordEncrypt = doc.data()["password"];
                password = cryptoJS;
                details.push({
                  site: {
                    email: emailId,
                    password: password,
                    keys: keys,
                  },
                });
                internalResolve();
              });
            });
        })
      );
    });
    Promise.all(promises).then(() => {
      console.log("5");
      console.log(details);
      resolve(details);
    });
  });
  getDs.then((details) => {
    console.log("rendering");
    return response.render("dashboard", {
      details: details,
      linkedSites: linkedSites,
      sites: sites,
    });
  });
});

更清洁async/await

indexRouter.get("/dashboard", checkSignIn, async (request, response) => {
  snapshot = await db.doc("users/accounts").get();
  sites = snapshot.data()["sites"];
  const userId = request.session.userId;
  snapshot = await db.doc(`users/${userId}`).get();
  var linkedSites = snapshot.data()["linked sites"];
  console.log("1");
  linkedSites.forEach(async (site) => {
    console.log("2");
    const snapshot = await db.doc(`users/${userId}`).collection(site).get();
    console.log("3");
    snapshot.forEach((doc) => {
      console.log("4");
      console.log(doc.id);
      emailId = doc.id;
      keys = doc.data()["keys"];
      var passwordEncrypt = doc.data()["password"];
      password = cryptoJS;
      details.push({
        site: {
          email: emailId,
          password: password,
          keys: keys,
        },
      });
    });
  });
  console.log("rendering");
  return response.render("dashboard", {
    details: details,
    linkedSites: linkedSites,
    sites: sites,
  });
});

推荐阅读