2017-05-31 37 views
0

我被困在我正在使用的函数(我可以做到这一切都是错误的)。所以快速解释一下,我想在一个集合中添加批量数据,集合称为“Sites”,CSV的格式是网站,国家,类型。我正在尝试使用此承诺(Bluebird)。因此,考虑代码:蓝鸟与猫鼬使用Promise.Each

Promise.each(sites, sites => new Promise((resolve, reject) => { 
    //console.log(sites); 
    let name = tools.extractDomain(req, res, sites[0]); 
    let country = sites[1]; 
    let group = sites[2]; 
    if (name != "" && country != "" && group != "") { 

     Site.findOne({ name: name }, "_id", function(err, duplicate) { 
      if (false) { 
       console.log("Duplicate site: " + duplicate); 

      } else { 
        //console.log("Adding " + name) 
       let site = new Site() 
       site.name = name 
       site.meta = {} 
       site.group = group 
       site.country = country 
       site.geomix = [] 
       site.addedBy = req.user._id 
       site.addedAt = Date.now() 
       site.saveAsync().then(function(response){ 
        tools.saveHistory(req, res, response._id, response.name, "Website Meta fetched."); 
        tools.saveHistory(req, res, response._id, response.name, "Link added for the first time."); //Save in history 
        resolve(site); 
       }).catch(function (e){ 
        console.log(name); 
        reject(); 
       }); 
      } 
     }); 

    }else{ 
     console.log('Wrong Format'); 
    } 
}).then((data) => { 
     console.log('All websites processed!'); 
     addedSites.push(data); 
}).catch(err => { 
     //console.error('Failed'); 
})); 

    res.send({ status: 'ok', message: ''}); 

我做Ajax调用,所以我返回res.send({状态:“OK”,邮件:“”}),我知道它在不正确的地方,我想要沿着res.send发送一些数据。目前它在代码实际完成之前发送标题。我想在Mongo中添加所有数据之后发送标题,但是在这种情况下,为了解决每个问题,我需要在“.each”的“.then”中发送标题,这样我会发送标题已经发送错误。

这可能有点混乱。我觉得我没有这样做。我有点疯了,以至于我找不到一个我能理解和实施的正确范例。

但最终我的主要问题是:使用Ajax调用什么是正确的添加方式让我们说使用承诺在集合中记录1000条记录,并实际控制那些添加失败和不添加的记录?

现在我的代码实际上工作,但逻辑肯定是错误的。

谢谢。

+1

避免['Promise'构造反模式](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-它)!如果您需要提供'Site.findOne',请在单独的函数中执行此操作(或让Bluebird为您执行此操作)。 – Bergi

回答

0

您可以在模型上使用bulkWrite

编号:http://mongoosejs.com/docs/api.html#model_Model.bulkWrite

编辑:

对不起,我误解你了。你需要移动res.send({ status: 'ok', message: ''});then()catch()块,所以你会得到这样的事情:

Promise.each(sites, sites => new Promise((resolve, reject) => { 
    // stuff you did before 
}).then((data) => { 
    console.log('All websites processed!'); 
    addedSites.push(data); 
    res.send({ status: 'ok', message: ''}); 
}).catch(err => { 
    res.send({ status: 'failed', message: err.message}); 
})); 
+0

不确定这是否有帮助。我意识到这个功能,我可以使用它,我仍然感到困惑,我的观点更多的是理解使用承诺进行批量处理和处理错误的正确方法。即使我实现bulkWrite,我仍然会遇到同样的问题。 – DanielPanic

+0

这样更好,但我仍然得出了这个结论。但是每次保存时都检查一次我有一个resolve(),所以他每次都在代码实际工作之前发送头文件(在我的前端中,status.ok和我向用户发送了一条警告,如果我把那个res.send放在那里的话。我通过计算要添加的记录的大小来修复它,并在它们都匹配时发送增量,并发送te头。不知道这是否是最“优雅”的方式 – DanielPanic

0

这是我来过,如果有人能告诉我,如果这是一个很好的弓。

exports.addBulkSite = function(req, res, next) { 
    let siteArray = csv.parse((req.body.sites).trim()), 
     addedSites = [], 
     failedSites = [], 
     duplicated = [], 
     sites = siteArray, 
     size = sites.length, 
     processed = 0, 
     meta; 
    Promise.each(sites, sites => new Promise((resolve, reject) => { 
     let name = tools.extractDomain(req, res, sites[0]), 
      country = sites[1], 
      group = sites[2]; 
     if (name != "" && country != "" && group != "") { 
      Site.findOneAsync({ name: name }, "_id").then(function(duplicate) { 
       duplicated.push(duplicate); 
       reject({name:name, message: 'Duplicated', critical:false});   
      }).catch(function(notDuplicated){ 
       let site = new Site() 
       site = { 
          name: name, 
          meta: {}, 
          group: group, 
          country: country, geomix:{}, 
          addedBy: req.user._id, 
          addedAt:Date.now() 
         } 
       site.saveAsync().then(function(response){ 
        tools.saveHistory(req, res, response._id, response.name, "Website Meta fetched."); 
        tools.saveHistory(req, res, response._id, response.name, "Link added for the first time."); //Save in history 
        resolve(site); 
       }).catch(function (e){ 
        console.log(e); 
        reject({name:name, message: 'Error saving in the database. Please contact the administrator.', critical: true}); 
       }); 
      }); 
     }else{ 
      reject({name:name, message: 'Paramaters are missing', critical:false}); 
     } 
    }).then((data) => { 
      processed++; 
      addedSites.push(data); 
      if(processed==size){ 
      console.log('out'); 
      res.send({ status: 'ok', addedSites: addedSites, failedSites: failedSites, duplicated: duplicated}); 
      } 
    }).catch((err) => { 
      processed++; 
      console.log(err); 
      failedSites.push(err); 
      if(processed==size){ 
      console.log('out'); 
      res.send({ status: 'ok', addedSites: addedSites, failedSites: failedSites, duplicated: duplicated}); 
      } 
    })); 
} 
+1

无论如何,当你使用'findOneAsync'时,避免['Promise' constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the -promise建设,反模式和如何对避免-吧)! – Bergi

+0

我正在阅读一些关于这方面的内容,但作为承诺的新手,我发现很难理解并将其放在我的代码中,如果能够使用我的代码更好地解释它,我会更喜欢。仍然做了一些研究,你的提示已经非常有用,因为它意味着它是正确的方向。谢谢。 – DanielPanic

+0

只需放下'新的Promise((resolve,reject)=> {'部分,而不是将'return'加入*每一个函数*,返回一个值或承诺(或抛出拒绝) – Bergi