2017-05-31 82 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