Асинхронный цикл не дождался

#node.js #arrays #asynchronous

#node.js #массивы #асинхронный

Вопрос:

Я использую node-async-loop для асинхронного программирования

 var array = ['item0', 'item1', 'item2'];
asyncLoop(array, function (item, next)
{
    do.some.action(item, function (err)
    {
        if (err)
        {
            next(err);
            return;
        }
 
        next();
    });
}, function (err)
{
    if (err)
    {
        console.error('Error: '   err.message);
        return;
    }
 
    console.log('Finished!');
});
 

Таким образом, я использую три асинхронных цикла один под одним.
Я хочу отправить ответ только после завершения третьего внутреннего цикла. Как я могу это сделать?.
Вот ссылка для узла-async-loop (https://www.npmjs.com/package/node-async-loop )

вот мой код, который я пишу, но всякий раз, когда я хочу ответить, когда завершается последний цикл, скажем, можно установить заголовок после отправки клиенту. также в журнале консоли я получаю данные каждый раз, когда данные поступают из запроса.

 const id = req.params.id;
    finalData = [];
    tb_user.findOne({ where: { id: id } }).then((userRiverSys, err) => {
        if (userRiverSys) {
            // console.log(userRiverSys.regionJson)
            asyncLoop(userRiverSys.regionJson, function (item, next) {
                // console.log("item", item);
                tb_riverSystems.findAll(
                    {
                        where: { regionId: item.id }
                    }).then((findriverSys, err) => {
                        if (err) {
                            next(err);
                            return;
                        }
                        // console.log("findriverSys", findriverSys);
                        if (findriverSys) {
                            asyncLoop(findriverSys, function (item1, next1) {
                                if (err) {
                                    next(err);
                                    return;
                                }
                                // console.log("item1", item1.dataValues);
                                tb_facilities.findAll(
                                    {
                                        where: { riverSystemId: item1.dataValues.id }
                                    }).then((findFacilities) => {
                                        if (findFacilities) {
                                            // console.log("findFacilities", findFacilities[0].dataValues.name);
                                            asyncLoop(findFacilities, function (item2, next2) {
                                                if (err) {
                                                    next(err);
                                                    return;
                                                }
                                                tb_userAccess.findAll(
                                                    {
                                                        where: { facilityId: item2.dataValues.id }
                                                    }).then((userAccessFacilities, err) => {
                                                        // console.log("userAccessFacilities", userAccessFacilities[0].dataValues);
                                                        // var i = 0;
                                                        asyncLoop(userAccessFacilities, function (item3, next3) {
                                                            finalData.push({
                                                                UserId: item3.userid,
                                                                facilityId: item3.facilityId,
                                                            })

                                                            next3();
                                                        },
                                                            function (err) {
                                                                if (err) {
                                                                    console.error('Error: '   err.message);
                                                                    return;
                                                                }
                                                                // i  ;
                                                                // console.log('Finished!!!!');
                                                                // if (userAccessFacilities.length === i) {
                                                                //  console.log("finalData", i);
                                                                //  // res.json({"status":"true", "message":"update OrgChallenge"})
                                                                //    }
                                                            })
                                                            return  res.json({"status":"true", "message":"update OrgChallenge"})
                                                        
                                                            // console.log("finalData", finalData);

                                                    })
                                                next2();
                                            }, function (err) {
                                                if (err) {
                                                    console.error('Error: '   err.message);
                                                    return;
                                                }
                                                console.log('Finished!!!');
                                            });
                                        }
                                    });
                                next1();
                            }, function (err) {
                                if (err) {
                                    console.error('Error: '   err.message);
                                    return;
                                }
                                console.log('Finished!!');
                            });
                        }
                    });
                next();
            }, function (err) {
                if (err) {
                    console.error('Error: '   err.message);
                    return;
                }
                console.log('Finished!');
            });

        } else {
            console.log("err3", err)
        }
    })
 

Комментарии:

1. Есть ли какая-либо причина, по которой вы хотите использовать этот пакет? Это можно легко сделать изначально, не полагаясь на дополнительный пакет.

2. Намного проще и проще кодировать это с помощью promises без использования какого-либо внешнего пакета.

3. я уже использовал этот пакет раньше, когда я отправлял только сообщение, но на этот раз нужно отправлять данные в qurery

4. @jfriend00 можете ли вы привести какой-нибудь пример, как я могу продолжить

5. @Harpritsingh — я привел пример в ответе.

Ответ №1:

Если вы обещаете свое асинхронное действие (чтобы оно возвращало обещание), тогда вы можете просто использовать обычный for цикл, async/await и нет необходимости в сторонней библиотеке для упорядочивания вашего асинхронного цикла. Это современный Javascript:

 const { promisify } = require('util');
do.some.actionP = promisify(do.some.action);

async function someFunction() {
    const array = ['item0', 'item1', 'item2'];
    for (let item of array) {
        let result = await do.some.actionP(item);
        // do something with result here
    }
    return someFinalResu<
}

someFunction().then(result => {
   console.log(result);
}).catch(err => {
   console.log(err);
});
 

К вашему сведению, в реальном коде многие (или даже большинство) асинхронных операций теперь уже предлагают обещанные версии своего API, поэтому обычно вам даже не нужно больше выполнять шаг promisify. Например, почти все базы данных уже предлагают интерфейс promise, который вы можете просто использовать напрямую.

Комментарии:

1. но я не работал с простым циклом for в цикле, потому что он прерывается, если данные составляют 1000 пользователей или более, поэтому я использую этот пакет

2. @Harpritsingh — если do.some.action() обратный вызов выполняется только по завершении, тогда этот цикл будет работать нормально, независимо от того, сколько у вас элементов, потому что цикл запускает элементы по одному за раз. Он не запускает второй, пока не будет выполнен первый. Это будет нормально работать с миллионами элементов. Ваша предыдущая попытка выполнить подобный цикл не содержала обещаний и await подобных тому, что я использую.

Ответ №2:

 const loop = async (arr, results = []) => {
  const item = arr.shift()
  if (!item) {
    console.log("DONE");
    return results;
  }

  // as async function
  await new Promise(resolve => {
    resolve(results.push(`asynced-${item}`))
  })

  return loop(arr, results);
}

(async () => {
  const result = await loop(["item0", "item1", "item2"])
  console.log(result);
})();
 

Я был бы рад, если смогу вам помочь.
но этот скрипт использует рекурсивную функцию вместо node-async-loop .
так что это может вам не подойти.

Комментарии:

1. это не сработает, значит, как работает этот код, я не понял