我需要处理大量数据。对于数据的每个条目,我们需要向mysql提交查询。我目前的解决方案如下:
var Q = require('q');
function process(entry){
...
var defered=Q.defer();
connection.query(sql,defered.makeNodeResolver());
return defered.promise;
}
function ProcessAll(results ) {
var waitfor=[];
for( var i=0;i< results.length;i++){
waitfor.push( process(results[i]));
}
Q.all(waitfor).then(function(results) {
notifySuc(results);
},function(results){
notifyFail(results);
});
}
但是,当数据量很大时,由于内存不足会导致数据崩溃:
FATAL ERROR: Committing semi space failed. Allocation failed - process out of memory
1: node::Abort() [node]
2: 0x109624c [node]
3: v8::Utils::ReportApiFailure(char const*, char const*) [node]
4: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [node]
5: v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [node]
6: v8::internal::Heap::CollectGarbage(v8::internal::GarbageCollector, char const*, char const*, v8::GCCallbackFlags) [node]
如何以较小的批次打破它?例如,我们每次可以处理1000个条目。在他们都是我们之后我们恢复其余的。如何使用回调函数?
另外,我们可以并行处理多个条目吗?
答案 0 :(得分:0)
您可以使用类似BaconJS的内容来执行此操作。您可以使用 Bacon.fromPromise(promise [,abort] [,eventTransformer])创建一个事件流,然后使用 stream.bufferWithCount(count)将您的处理分解为批次。 BaconJS 是一个小型的功能反应式编程库。要了解有关FRP的更多信息,您可以阅读The Introduction to FRP以获得快速入门。
答案 1 :(得分:0)
如果错误不是由notifySuc
引起的,您可以按照以下方式轻松处理批次
var Q = require('q');
function process(entry){
...
var defered=Q.defer();
connection.query(sql,defered.makeNodeResolver());
return defered.promise;
}
function processBatch(batch) {
return Q.all(batch.map(item => process(item)));
}
function ProcessAll(results) {
var batchSize = 1000;
var pos = 0;
var promises = Q([]); // initial promise of empty array
while (pos < results.length) {
(function(pos) {
promises = promises.then(result => processBatch(results.slice(pos, batchSize)).then(results => result.concat(results)));
})(pos);
pos += batchSize;
}
promises.then(function(results) {
notifySuc(results);
},function(results){
notifyFail(results);
});
}