Невозможно выполнить асинхронную итерацию по массиву с асинхронным блоком, используя async.each () - PullRequest
0 голосов
/ 10 июня 2018

У меня есть некоторые асинхронные функции, которые я хочу выполнить для каждого из элементов в массиве currencyData, как показано ниже.У меня есть следующая логика -

exports.getCurrenciesOfMerchant(req,res,function(currencyData)
{
     async.each(currencyData, function (eachCurrency) {
        fieldObject.currencyId=eachCurrency;
        console.log("See currencyData "+fieldObject.currencyId);

//async block starts here   
        couponHandler.checkIFWalletExists(res,fieldObject,function(fieldObject)
        {
            console.log("checked wallet for curr "+fieldObject.currencyId);
            if(fieldObject.hasWallet == 0)
            {
                exports.createWalletForUser(fieldObject,res,function(fieldObject,res){
//                        exports.createCoupon(fieldObject,res,function(res,fieldObject,couponId){
//                            return exports.couponCreationResponse(res,fieldObject,couponId);
//                        });
                    console.log("created wallet");
                });
            }
        });
    });
});

Следующий вывод -

See currencyData 5
See currencyData 6
checked wallet for curr 6
checked wallet for curr 6
created wallet
created wallet

Как видно, async.each () принял значение 6 до завершения выполнения асинхронного блока,На самом деле он никогда не запускал логику для значения 5.

Я думал, что именно здесь async.each () будет полезен.Но я не мог заставить это работать.Пробовал использовать async.forEachOf, но получил те же результаты.

Ответы [ 2 ]

0 голосов
/ 10 июня 2018

Вы не вызываете предоставленный обратный вызов «done», поэтому async не знает, что асинхронная операция завершена, и не будет продолжать обработку остальных элементов.Измените итератор на

async.each(currencyData, function (eachCurrency, done) {

и вызовите функцию done в самом внутреннем обратном вызове.

exports.createCoupon(fieldObject,res,function(res,fieldObject,couponId){
    var res = exports.couponCreationResponse(res,fieldObject,couponId);
    done();
    return res;
});

Edit: ... а также вКонечно же, там есть ветка else вашего условного if.

} else {
   done();
} 

Если вы не хотите, чтобы элементы обрабатывались одновременно, используйте async.eachLimit вместо этого:

async.eachLimit(currencyData, 1, function (eachCurrency, done) {
0 голосов
/ 10 июня 2018

doc говорит:

Применяет функцию iteratee к каждому элементу в coll, параллельно.Итератор вызывается с элементом из списка и обратным вызовом, когда он завершится.Если итератор передает ошибку в свой обратный вызов, основной обратный вызов (для каждой функции) немедленно вызывается с ошибкой.

Обратите внимание, что, поскольку эта функция применяет итератора к каждому элементу параллельно, нет гарантиичто функции iteratee будут завершены по порядку.

Я полагаю, что метод couponHandler.checkIFWalletExists не закомментирован в вашем коде.Это означает, что итератор начнет обработку второго элемента до того, как завершит обработку первого.И, вероятно, из-за того, что второй элемент обрабатывается быстрее, вы видите результаты в неправильном порядке.

...