对象未推送到forEach()方法中的数组

时间:2020-08-20 19:56:59

标签: javascript sql postgresql express

我正在使用Express路由,因此我不确定为什么在这些数据库调用结束时我的“ purchasedCards”数组为空。我首先从几个数据库查询中收集了我需要的所有信息,然后将其放入上下文中以发送到前端。所有的数据库调用都工作正常……甚至是cardUpdator对象。我唯一的问题是将对象推入数组...

我对使用postgres数据库/ SQL是陌生的。任何建议都值得赞赏。

    //User Account
router.get('/account', isLoggedIn, (req, res) => {
  //Get User Info - First get the user info
  db.query(`SELECT * FROM users WHERE userid = '${res.locals.user.id}';`)
  .then(user => {
    //Get user Purchases
    db.query(`SELECT * FROM purchases WHERE newowner = '${res.locals.user.id}';`)
    .then(purchases => {
      let purchasedCards = []
      //Get Card Info for Each Purchase
      purchases.forEach( purchasedCard => {
        //Get the card from user_cards table for standard card info.
        db.query(`SELECT * FROM user_cards WHERE id = '${purchasedCard.card}';`)
        .then( card => {
          //Get Old Owner Info
          db.query(`SELECT * FROM users WHERE userid = '${purchasedCard.oldowner}';`)
          .then(oldOwner => {
            let cardUpdator = {
              cardName: card[0].name,
              cardGame: card[0].game,
              cardOldOwner: oldOwner[0].screen_name,
              cardPID: purchasedCard.purchaseid,
              cardTotal: purchasedCard.total,
              cardId: purchasedCard.card,
            }
            purchasedCards.push(cardUpdator)
          })
        })
      })
      let context = {
        name: user[0].screen_name,
        email: user[0].email,
        purchases: purchasedCards,
      }
      res.render('MyAccount.hbs', context) 
    })
  })
})

2 个答案:

答案 0 :(得分:0)

您应该等待异步操作完成使用Promise。为了使代码更简洁,请使用async await。

//User Account
router.get('/account', isLoggedIn, (req, res) => {
  //Get User Info - First get the user info
  db.query(`SELECT * FROM users WHERE userid = '${res.locals.user.id}';`)
  .then(user => {
    //Get user Purchases
    db.query(`SELECT * FROM purchases WHERE newowner = '${res.locals.user.id}';`)
    .then(purchases => {
      //Get Card Info for Each Purchase
      let getCardPromises = purchases.map(purchasedCard => {
        //Get the card from user_cards table for standard card info.
        return db.query(`SELECT * FROM user_cards WHERE id = '${purchasedCard.card}';`)
        .then( card => {
          //Get Old Owner Info
          return db.query(`SELECT * FROM users WHERE userid = '${purchasedCard.oldowner}';`)
          .then(oldOwner => {
            let cardUpdator = {
              cardName: card[0].name,
              cardGame: card[0].game,
              cardOldOwner: oldOwner[0].screen_name,
              cardPID: purchasedCard.purchaseid,
              cardTotal: purchasedCard.total,
              cardId: purchasedCard.card,
            }
            return cardUpdator;
          })
        })
      })
      Promise.all(getCardPromises).then(getOwnerPromises => {
        Promise.all(getOwnerPromises).then(purchasedCards => {
          let context = {
            name: user[0].screen_name,
            email: user[0].email,
            purchases: purchasedCards,
          }
          res.render('MyAccount.hbs', context) 
        })
      })
    })
  })
})

编辑,我添加了async / await版本,绝对使代码更简洁

//User Account
router.get('/account', isLoggedIn, async (req, res) => {
    //Get User Info - First get the user info
    let user = await db.query(`SELECT * FROM users WHERE userid = '${res.locals.user.id}';`)
    let purchases = await db.query(`SELECT * FROM purchases WHERE newowner = '${res.locals.user.id}';`)
    //Get Card Info for Each Purchase
    let purchasedCardsPromises = purchases.map(async (purchasedCard) => {
        //Get the card from user_cards table for standard card info.
        let [card, oldOwner] = await Promise.all([  db.query(`SELECT * FROM user_cards WHERE id = '${purchasedCard.card}';`),
                                                    db.query(`SELECT * FROM users WHERE userid = '${purchasedCard.oldowner}';`)])
        let cardUpdator = {
            cardName: card[0].name,
            cardGame: card[0].game,
            cardOldOwner: oldOwner[0].screen_name,
            cardPID: purchasedCard.purchaseid,
            cardTotal: purchasedCard.total,
            cardId: purchasedCard.card,
        }
        return cardUpdator;
    })
    let purchasedCards = await Promise.all(purchasedCardsPromises)
    let context = {
    name: user[0].screen_name,
    email: user[0].email,
    purchases: purchasedCards,
    }
    res.render('MyAccount.hbs', context)
})

答案 1 :(得分:0)

最好使用async / await来避免多个回调。但是,出现意外行为的原因是因为您试图在已购买的Cards之前进行访问。这是因为JavaScript在本机中是异步的,因此在您访问PurchaseCards时,诺言尚未解决。

我有一个建议,如果您选择的话可以遵循,我使用了async / await。希望它会有所帮助。

async function getPurchasedCards(purchases) {
  const purchasedCards = [];
  return purchases.forEach((purchasedCard) => {
    //Get the card from user_cards table for standard card info.
    db.query(
      `SELECT * FROM user_cards WHERE id = '${purchasedCard.card}';`,
    ).then((card) => {
      //Get Old Owner Info
      db.query(
        `SELECT * FROM users WHERE userid = '${purchasedCard.oldowner}';`,
      ).then((oldOwner) => {
        let cardUpdator = {
          cardName: card[0].name,
          cardGame: card[0].game,
          cardOldOwner: oldOwner[0].screen_name,
          cardPID: purchasedCard.purchaseid,
          cardTotal: purchasedCard.total,
          cardId: purchasedCard.card,
        };
        purchasedCards.push(cardUpdator);
        if (purchasedCards.length === purchases.length) return purchasedCards;
      });
    });
  });
}

async function getPurchasedCards(purchases) {
  const purchasedCards = [];
  return purchases.forEach((purchasedCard) => {
    //Get the card from user_cards table for standard card info.
    db.query(
      `SELECT * FROM user_cards WHERE id = '${purchasedCard.card}';`,
    ).then((card) => {
      //Get Old Owner Info
      db.query(
        `SELECT * FROM users WHERE userid = '${purchasedCard.oldowner}';`,
      ).then((oldOwner) => {
        let cardUpdator = {
          cardName: card[0].name,
          cardGame: card[0].game,
          cardOldOwner: oldOwner[0].screen_name,
          cardPID: purchasedCard.purchaseid,
          cardTotal: purchasedCard.total,
          cardId: purchasedCard.card,
        };
        purchasedCards.push(cardUpdator);
        if (purchasedCards.length === purchases.length) return purchasedCards;
      });
    });
  });
}