首页 > 解决方案 > Javascript/NodeJS:在 forEach 内完成 .find 之前的 html 渲染

问题描述

这个循环应该检查数据库中与从 salesforce api 结果中提取的 opps 匹配的 opps,然后创建一个新的 opp 或找到现有的 opp 并将其推送到数组。似乎 res.render 在找到 opp 之前正在运行。它创建了一个新的 opp,但在页面呈现时数组返回空。

 Account.find({owner:req.user._id, prospect:'false'}).sort({ammount:'desc'}).populate({path: "notes", options:{ sort:{ 'date': -1 } } }).exec(function(err, allAccounts) {
        let callGoal = req.user.callGoal;
        if(err){
            res.send(err);
        }else{
            // if auth has not been set, redirect to index
            if (!req.session.accessToken || !req.session.instanceUrl) { res.redirect('/'); }
        //SOQL query
            let q = "SELECT Id,Amount,CloseDate,LastActivityDate,Name,StageName,account.Name FROM Opportunity WHERE CloseDate < 2018-10-01 AND OwnerId = '0050a00000J12PdAAJ' AND IsClosed = false AND StageName != 'Stage 6: Won'";
        //instantiate connection
            let conn = new jsforce.Connection({
                oauth2 : {oauth2},
                accessToken: req.session.accessToken,
                instanceUrl: req.session.instanceUrl
           });
        //set records array
            let softopps = [];
            let sfOpps = [];
            let query = conn.query(q)
               .on("record", function(record) {
                 sfOpps.push(record);
               })
               .on("end", function() {
                 console.log("total in database : " + query.totalSize);
                 console.log("total fetched : " + query.totalFetched);
                 let user = req.user;
                 sfOpps.forEach(function(sfopp){
                     if(err){
                         res.send(err);
                     }else{
                         Opp.findOne({sfid:sfopp.Id}).exec(function(err, opp){
                         if(!opp.length){
                            Opp.create(req.body, function(err, newOpp) {
                                if(err){
                                    res.send(err)
                                }else{
                                    newOpp.sfid = sfopp.Id;
                                    newOpp.name = sfopp.Name;
                                    newOpp.owner = user.sfid;
                                    newOpp.save();
                                    return softopps.push(newOpp)
                                }
                            })
                         }else{
                             return softopps.push(opp);
                         }
                     })
                     }
                 })
                 res.render("myaccounts", {accounts:allAccounts, callGoal:callGoal, user:user, sfOpps:sfOpps, opps:softopps});
               })
               .on("error", function(err) {
                 console.error(err);
               })
               .run({ autoFetch : true, maxFetch : 4000 });
        }
    });

标签: javascriptnode.jsmongodbmongoose

解决方案


你的Opp.findOne()Opp.create()调用是异步的,所以它们在res.render().


另一方面,你几乎用所有不必要的请求杀死了你的 mongodb。

试试这个逻辑(从 开始.forEach

  1. Opp通过 id查找所有ssfOpps
  2. 找出哪些Opps 没有找到并创建它们
  3. 连接所有找到的和未找到Opp
  4. 然后,然后才回应

我没有测试该代码,但它可以大致让您了解我的意思

Opp.find({ sfid : { $in: sfOpps.map(opp => opp.id) } })
  .then(found => {

    const foundIds = found.map(opp => opp.sfid)
    const notFound = sfOpps.filter(opp => !foundIds.includes(opp.sfid)).map(sfopp => {
      return {
        sfid: sfopp.sfid,
        name: sfopp.name,
        owner: user.sfid
      }
    })

    Opp.insertMany(notFound)
      .then((insertResult) => {

        res.render("myaccounts", {
          accounts: allAccounts, 
          callGoal: callGoal, 
          user: user, 
          sfOpps: found.concat(notFound), 
          opps: softopps
        });

      }).catch(handleError)

  }).catch(handleError)

推荐阅读