异步循环没有等待

Posted

技术标签:

【中文标题】异步循环没有等待【英文标题】:Async loop didn't wait 【发布时间】:2021-04-15 04:27:39 【问题描述】:

我正在使用 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!');
);

像这样,我使用三个异步循环,一比一。 我只想在第三个内部循环结束后发送响应。我该怎么做? 这是节点异步循环的链接(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)
        
    )

【问题讨论】:

你有什么理由要使用这个包吗?这可以在本地轻松完成,无需依赖额外的包。 在不使用任何外部包的情况下,使用 Promise 编写代码更简单。 我之前使用过这个包,我只发送消息,但这次需要在 qurery 中发送数据 @jfriend00 你能给我一些例子,我该如何继续 @Harpritsingh - 我在回答中提供了一个例子。 【参考方案1】:

如果您承诺您的异步操作(因此它返回一个承诺),那么您可以只使用常规的for 循环和async/await,并且不需要第 3 方库来对您的异步循环进行排序。这是现代 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 someFinalResult;


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

仅供参考,在实际代码中,许多(甚至大多数)异步操作现在已经提供了其 API 的 Promisify 版本,因此通常您甚至不需要再执行 Promisify 步骤。例如,几乎所有数据库都已经提供了一个可以直接使用的 Promise 接口。

【讨论】:

但我没有使用简单的 for in 循环,因为如果数据是 1000 个或更多用户,它会中断,所以我使用这个包 @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。 所以这可能不适合你。

【讨论】:

这不起作用意味着我不明白这段代码是如何工作的

以上是关于异步循环没有等待的主要内容,如果未能解决你的问题,请参考以下文章

如何等待来自 for 循环的多个异步调用?

异步、等待和无限循环

等待所有异步请求在循环内完成[重复]

如何等待来自 forEach 循环的多个异步调用?

在赛普拉斯的 for 循环中等待异步方法

java 异步查询转同步多种实现方式:循环等待,CountDownLatch,Spring Even