NodeJS Async - Предаване на параметри за обратно извикване

Настройвам скрепер с помощта на NodeJS и ми е трудно да разбера правилния начин за предаване на данни, когато използвам async.parallel.

Ето пакетната функция, която получава списъка с пощенски кодове в масив вътре в обекта zip_results. Опитвам се да настроя масива asyncTasks като масив от функции, които да се изпълняват от async. Функцията, която искам да се извиква за всеки пощенски код, е 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() в горния пример), когато приключим с елемента. Ако вашата партида работи асинхронно, ще трябва да предадете next като параметър във функцията batchOne и да я извикате, когато сте готови. - person Reto; 24.02.2015