пакетный режим с обещанием в javascript

111
13

Мне нужно обработать много данных. Для каждой записи данных нам нужно отправить запрос в 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 записей каждый раз. После того, как они все, мы возобновим все остальное. Как это сделать с функциями обратного вызова?

Кроме того, можно ли обрабатывать несколько записей параллельно?

спросил(а) 2021-01-19T16:03:57+03:00 8 месяцев назад
1
Решение
112

Если ошибка не вызвана 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);
});
}

ответил(а) 2021-01-19T16:03:57+03:00 8 месяцев назад
47

Вы можете использовать что-то вроде BaconJS для этого. Вы можете создать поток событий с Bacon.fromPromise (обещание [, прервать] [, eventTransformer]), а затем использовать stream.bufferWithCount(count), чтобы разбить вашу обработку на партии. BaconJS - небольшая библиотека функционального реактивного программирования. Чтобы узнать больше о FRP, вы можете прочитать "Введение в FRP" для быстрого праймера.

ответил(а) 2021-01-19T16:03:57+03:00 8 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема