2013-06-03 41 views
0

我有一個字符串Node.js的異步陣列將數據保存到MongoDB的

var my_str = "Jenny [id:51], david, Pia [id:57], Aston [id:20], Raj, "; 

我送這個給函數convert_to_array(my_str),並希望這樣的事情作爲回報

[all: [51, 72, 57, 20, 73], new: [72, 73]] 

這裏,是新插入的文件到mongodb數據庫。

這是我在做什麼:

function convert_to_array(text) { 
if(text && text !== '') { 

    var text_arr = text.split(', '); 
    text_arr.pop(); 

    var arr = new Array(); 
    var new_profiles = new Array(); 
    var all_profiles = new Array(); 

    for(var i = 0; i < text_arr.length; i++) { 
     var pair = text_arr[i].split('[id:'); 

     // Its already existing, just add it to the array 
     if(pair[1]) { 
      all_profiles.push(pair[1].split(']')[0]); 

     // Else create a new profile and pass the _id 
     } else { 

      // Save to db first 
      var profileObj = new Profile({name: pair[0], automated: true}); 
      profileObj.save(function(err, data) { 

       if(err) throw err; 

       all_profiles.push(String(data._id)); 
       new_profiles.push(String(data._id)); 
      }); 
     } 
    } 
    arr = {all: all_profiles, new: new_profiles}; 
    return arr; 
} 
} 

有了這個代碼,我只得到這個(或類似的東西,我不記得確切的輸出)

[all: [51, 57, 20], new: []] 

該項目被保存在數據庫中,我可以看到。但由於節點本質上是非阻塞的,因此for循環在數據保存到數據庫&並將ID推送到aray之前完成並返回。我嘗試了異步,但仍然無法弄清楚如何解決這個問題。

我加幾console.logs,看它如何執行,這裏有雲:

yes existing: 51 
oh! doesnt exist. creating: david 
yes existing: 57 
yes existing: 20 
oh! doesnt exist. creating: Raj 
GET /page/delete_later 200 4ms 
Ok created now: 72 
Ok created now: 73 

我如何編寫它節點友好這麼糊塗!

回答

1

您需要更改convert_to_array函數,以便在結果完成時調用回調函數,而不是返回結果的返回值。

​​

現在當你的結果準備好了嗎?這是所有text_arr項目處理完畢(即所有對profileObj.save的呼叫都完成)。如何在代碼中表達這個最簡單的方法是使用異步模塊(npm install async):

var async = require('async'); 
// ... 

function convert_to_array(text, callback) { 
    if(text && text !== '') { 

    var text_arr = text.split(', '); 
    text_arr.pop(); 

    var arr = new Array(); 
    var new_profiles = new Array(); 
    var all_profiles = new Array(); 

    async.eachSeries(text_arr, function(it, done) { 
     var pair = text_arr[i].split('[id:'); 

     // Its already existing, just add it to the array 
     if(pair[1]) { 
     all_profiles.push(pair[1].split(']')[0]); 
     next(); // !important! tell async we are done 
     // Else create a new profile and pass the _id 
     } else { 
     // Save to db first 
     var profileObj = new Profile({name: pair[0], automated: true}); 
     profileObj.save(function(err, data) { 
      if(err) { 
       // throw err; // use callback instead of throw for error handling 
       next(err); 
       return; 
      } 
      all_profiles.push(String(data._id)); 
      new_profiles.push(String(data._id)); 
      next(); // !important! tell async we are done 
     }); 
    }, function(err) { 
     arr = {all: all_profiles, new: new_profiles}; 
     callback(err, arr); 
    } 

    } else { 

    callback(null, undefined); // alter depending on your requirements 
    } 
} 
+0

謝謝Miroslave!我會盡快嘗試。其實我爲此玩了async.eachSeries,但無法讓它返回我想要的東西。在完成.save()之後,我認爲它的next()調用!異步的自述非常令人困惑:p –

相關問題