2015-07-21 60 views
1

我試圖讓下面的簡化代碼來完成,然後同步前進:的Node.js/Sails.js - 功能在forEach循環

factors.forEach(function(factor, index){ 
    Factor.findOrCreate({function_name: factor}).exec(function(){ 
    sails.log('success'); 
    }) 
}); 

我該怎麼辦呢?


到目前爲止,我已經嘗試:在一個單獨的函數

  • 把2-4行,並要求從 環
  • 使用async.js async.series內()調用

雖然它會執行調用(print'success'),但它會很少在DB中找到或創建一個因子,所以它與異步特性有關代碼。

  • 使用的承諾,等到所有findOrCreate()調用返回,然後繼續

    var promises = []; 
    factors.forEach(function(factor, index){ 
        promises.push(Factor.findOrCreate({function_name: factor})); 
    }); 
    Q.all(promises).then(function(){ 
        sails.log('success'); 
    }); 
    

我已經試過這一個了幾個版本,但我仍然不能得到它打印'成功' - 這似乎是正確的做法,但我不確定有什麼不對。

+0

您認爲「不經常工作」與查詢是並行處理而不是按順序處理有關嗎? – Bergi

+0

這是我的假設,這就是爲什麼我想要嘗試async.series()和承諾。我所做的所有測試似乎都強化了這一概念。 – smileham

回答

2

這樣做不使用async或承諾的一種簡單的方法是手動跟蹤多少條記錄都已經被處理:

var ctr = 0; 
factors.forEach(function(factor, index){ 
    Factor.findOrCreate({function_name: factor}).exec(function(err, factorObj){ 
     if (err) errorHandler(err); 
     ctr ++; 
     if (ctr === factors.length) { 
      successCallback(); 
     } 
    }); 
}); 

successCallback()將只叫畢竟Factor對象已被創建。

更新

或者,你可以試試這個完全避免循環:

Factor.findOrCreate(factors).exec(function(err, factorObjArray){ 
    callback(err, factorObjArray); 
}); 
+0

這也似乎是正確的,但是當我跑它,我得到了與其他答案相同的結果: 2/5:不打印任何東西或改變數據庫。 3/5:錯誤(E_UNKNOWN)::遇到意外錯誤:無法連接到MySQL:錯誤:池已關閉。之後在.../node_modules/sails-mysql/lib/connections/spawn.js:40:7之後(.../node_modules/sails-mysql/lib/connections/spawn.js:72:13) _tickDomainCallback(node.js:463:13)詳細信息:錯誤:無法連接到MySQL:錯誤:池已關閉。 – smileham

+0

您提到的錯誤指向數據庫連接錯誤。嘗試重新啓動數據庫或關閉所有打開的連接。 – galactocalypse

+0

它不必與帆。您的游泳池尺寸太小或其他應用程序佔用連接。你重新啓動數據庫後再試一次嗎? – galactocalypse

2

有這樣使用async.js庫forEachOf method的簡單方法。

例:

var async = require('async'); 
var promises = []; 
async.forEachOf(factors,function(factor, key, callback){ 
    Factor.findOrCreate({function_name: factor}).exec(function(result,err){ 
    if (err) { 
     callback(err); 
    } else { 
     promises.push(result); 
     callback(); 
    } 
    }); 
}, function(err){ 
    if (err) { 
    console.log("Error: "+err); 
 } else { 
    console.log(promises); 
    } 
}); 
+0

我跑了這五次,結果如下: 2/5: 不打印任何東西或改變數據庫。 3/5: 錯誤(E_UNKNOWN)::遇到意外錯誤 :無法連接到MySQL: 錯誤:池已關閉。 at .../node_modules/sails-mysql/lib/connections/spawn.js:40:7 (.../node_modules/sails-mysql/lib/connections/spawn.js:72:13)在process._tickDomainCallback(node.js:463:13) 詳細信息:錯誤:無法連接到MySQL: 錯誤:池已關閉。 – smileham

+0

這似乎是正確的,所以它必須是與帆可能... – smileham

1

你需要使用類似Q,承諾。但以適當的異步方式。

var cb = function(factor) { 
    var deferred = Q.defer(); 
    Factor.findOrCreate({function_name: factor}) 
    .exec(function(err, factorObj) { 
     if(err) deferred.reject(err); 
     deferred.resolve(factorObj); 
    }); 
    return deferred.promise; 
}; 

var promises = []; 
Factor.forEach(function(f) { 
    promises.push(cb(f)); 
}); 

Q.all(promises) 
    .then(function() { // You can get the params too. 
    console.log('WE ARE THE CHAMPIONS!!'); 
    }) 
    .fail(function() { // You can get the error params too. 
    console.log('WE LOOSE'); 
    }); 

希望它有幫助!它只是一個例子,自從我停止使用NodeJS和SailsJS幾個月後(不幸的是)。

+1

請注意,sails確實支持承諾,因此您應該避免[deferred antipattern](http://stackoverflow.com/q/23803743/1048572)。 – Bergi