NodeJS Async — передать параметры обратному вызову

Я настраиваю парсер с помощью NodeJS, и мне трудно понять, как правильно передавать данные при использовании async.parallel.

Вот пакетная функция, которая получает список почтовых индексов в массиве внутри объекта zip_results. Я пытаюсь настроить массив asyncTasks как массив функций, которые будут запускаться асинхронно. Функция, которую я хочу вызвать для каждого почтового индекса, называется Scraper.batchOne, и я хочу передать ей почтовый индекс и версию задания. Прямо сейчас функция вызывается немедленно. Я попытался обернуть вызов Scraper.batchOne в анонимную функцию, но это потеряло область действия индексной переменной i и всегда отправляло неопределенные значения.

Как сделать так, чтобы функция передавалась в массив вместе с некоторыми параметрами?

// zip_results: {job_version: int, zip_codes: []}
Scraper.batch = function (zip_results) {
    //tasks - An array or object containing functions to run, each function
    //is passed a callback(err, result) it must call on completion with an
    //error err (which can be null) and an optional result value.
    var asyncTasks = [], job_version = zip_results.job_version;
    for (var i=0; i < zip_results['zip_codes'].length; i++) {
        asyncTasks.push(Scraper.batchOne(zip_results['zip_codes'][i], job_version));
    }
    // Call async to run these tasks in parallel, with a max of 2 at a time
    async.parallelLimit(asyncTasks, 2, function(err, data) { console.log(data); });

};

person charmeleon    schedule 19.02.2015    source источник


Ответы (2)


Вы можете выполнить самовызывающуюся анонимную функцию и передать параметры, которые вы хотите сохранить после вызова метода, следующим образом:

(function(asyncTasksArr, index, zipResults, jobVersion){
    return function(){
        asyncTasksArr.push(Scraper.batchOne(zipResults['zip_codes'][index], jobVersion));
    }
}(asyncTasks, i, zip_results, job_version));

Надеюсь это поможет.

person skay-    schedule 19.02.2015
comment
Но разве это не будет выполняться сразу при загрузке? В этом случае Scraper.batch уже является обратным вызовом чего-то другого. - person charmeleon; 20.02.2015
comment
Внешняя функция, которая устанавливает область, будет вызываться onload... Внутренняя будет вызываться только при вызове «parallelLimit». - person skay-; 20.02.2015
comment
Ах, дурачок, ты абсолютно прав. Теперь моя проблема в том, что когда я вызываю async.parallelLimit(tasks, number_of_runs), он останавливается, как только я получаю number_of_runs итераций. Любая подсказка, почему это может происходить? - person charmeleon; 20.02.2015

Почему бы вам вместо этого не использовать async.eachLimit? (С async.parallel вам нужно будет использовать методы связывания/применения)

async.eachLimit(zip_results['zip_codes'], 2, function(zip, next) {
    Scraper.batchOne(zip, zip_results.job_version));
    return next();
}, function(err) {
     // executed when all zips are done
});
person Reto    schedule 19.02.2015
comment
Похоже, все начинается нормально, но после обработки первых двух результатов процесс просто зависает. - person charmeleon; 20.02.2015
comment
Я отредактировал решение, конечно, нам нужно вызвать обратный вызов (next() в приведенном выше примере), когда мы закончим с элементом. Если ваш пакет работает асинхронно, вам нужно будет передать следующий параметр в функцию batchOne и вызвать его, когда вы закончите. - person Reto; 24.02.2015