Javascript / NodeJS:.find在forEach内部完成之前的HTML呈现

时间:2018-09-27 05:37:53

标签: javascript node.js mongodb mongoose

该循环应该在数据库中检查与从salesforce api结果中提取的opp相匹配的opp,然后创建新的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 });
        }
    });

2 个答案:

答案 0 :(得分:0)

您的Opp.findOne()Opp.create()调用是异步的,因此它们在res.render()之后触发。


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

请尝试以下逻辑(从.forEach开始)

  1. 通过Opp的ID查找所有sfOpps s
  2. 找出未找到的Opp,并创建它们
  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)

答案 1 :(得分:0)

当页面由于创建/查找opps的调用是异步的而使您的页面仍然是空的而您的页面却是同步的,这就是为什么您的页面在调用完成之前首先呈现的原因。我认为您应该尝试使用async.eachOfSeries (coll,iteratee,回调),而不是sfOpps.forEach()。

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;
                 async.eachOfSeries(sfOpps,function(sfopp,next){
                     if(err){

                         next(err);
                     }else{
                         Opp.findOne({sfid:sfopp.Id}).exec(function(err, opp){
                         if(!opp.length){
                            Opp.create(req.body, function(err, newOpp) {
                                if(err){

                                    next(err);
                                }else{
                                    newOpp.sfid = sfopp.Id;
                                    newOpp.name = sfopp.Name;
                                    newOpp.owner = user.sfid;
                                    newOpp.save();
                                    softopps.push(newOpp);
                                    next();
                                }
                            })
                         }else{
                             softopps.push(opp);
                             next();

                         }
                     })
                     }
                 },function(err){
                  if (err) res.send(err);
                  else {
               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 });
        }
    });

我希望这会对您有所帮助。