node中循环异步的问题[‘解决方案‘]_源于map循环和for循环对异步事件配合async、await的支持

简介: 本文探讨了在Node.js中处理循环异步操作的问题,比较了使用map和for循环结合async/await处理异步事件的差异,并提供了解决方案。

首县,我先说一下我这个虚拟的需求,我从数据库中查找所有用户的信息,包括省市县,但是我存储的时候是以省码、市码、县码code的形式来存储到数据库的,所有我取出来的时候还需要去数据库省市县表中查找对应的name,所有产生了这个问题。

刚开始的思路很直接,很明确,就是找到所有人数据之后,进行循环,插入新属性,返回数据给前端。

//所有 user 用户信息
router.get('/queryAllUserInfo', async function (req, res, next) {
   
    let data = await Db.DBFunPro(`select user_info.uuid,user_info.name,user_info.sex,user_info.tel,user_info.pro,user_info.city,user_info.area,user.username,user.password,user_info.fileUrl from  user_info, user  where user.uuid = user_info.uuid`)
    let forFun = async (item) => {
   
        let prostr = await Db.DBFunPro(`select pro_name from pros where pro_id='${
     item.pro}'`)
        let citystr = await Db.DBFunPro(`select city_name from cities where city_id='${
     item.city}'`)
        let areastr = await Db.DBFunPro(`select area_name from areas where area_id='${
     item.area}'`)
        return prostr[0].pro_name + citystr[0].city_name + areastr[0].area_name
    }
    data.map(async item=>{
   
     let codeStr =  await  forFun(item)
        item.codeStr = codeStr
         console.log(item,'item');
    })
    res.send(endMassage(data))
});

上面的代码并不能解决问题,并没有将字段codeStr加上,但是在node端能打印到已经加上了,看下面两个图:
在这里插入图片描述
这是前端截图,发现并没有codeStr字段,但是:
在这里插入图片描述
node端打印是能获取到值的。发生了异步事件。

分割线==========================================================

分析:

在返回之后,map循环中的forFun才执行完,map循环的参数一个函数,map循环完一次调用多个函数,每一个函数的第一个参数item就是数组的每一项,map只管执行回调函数item=>{},只要这个执行完,就算执行完,并不管你这个函数里面是否是异步,所以,并不能通过async await的形式控制map循环。

当然,我们换一种形式,我们将循环放到函数里面 ,控制函数异步

//所有 user 用户信息
router.get('/queryAllUserInfo', async function (req, res, next) {
   
    let data = await Db.DBFunPro(`select user_info.uuid,user_info.name,user_info.sex,user_info.tel,user_info.pro,user_info.city,user_info.area,user.username,user.password,user_info.fileUrl from  user_info, user  where user.uuid = user_info.uuid`)
    let forFun = async (item) => {
   
        let prostr = await Db.DBFunPro(`select pro_name from pros where pro_id='${
     item.pro}'`)
        let citystr = await Db.DBFunPro(`select city_name from cities where city_id='${
     item.city}'`)
        let areastr = await Db.DBFunPro(`select area_name from areas where area_id='${
     item.area}'`)
        return prostr[0].pro_name + citystr[0].city_name + areastr[0].area_name
    }
    let datap = async () => {
   
        //map加不上
         data.map(async item => {
   
            let codeStr = await forFun(item)
            item.codeStr = codeStr
            console.log(item,'item');
        })
        return data
    }
    let datap2 = await datap()
    res.send(endMassage(datap2))
});

同样的,这也不行,原因和上面一样。

分割线==========================================================

下面我们不适用map来实现一下,我们使用for:

//所有 user 用户信息
router.get('/queryAllUserInfo', async function (req, res, next) {
   
    let data = await Db.DBFunPro(`select user_info.uuid,user_info.name,user_info.sex,user_info.tel,user_info.pro,user_info.city,user_info.area,user.username,user.password,user_info.fileUrl from  user_info, user  where user.uuid = user_info.uuid`)
    let forFun = async (item) => {
   
        let prostr = await Db.DBFunPro(`select pro_name from pros where pro_id='${
     item.pro}'`)
        let citystr = await Db.DBFunPro(`select city_name from cities where city_id='${
     item.city}'`)
        let areastr = await Db.DBFunPro(`select area_name from areas where area_id='${
     item.area}'`)
        return prostr[0].pro_name + citystr[0].city_name + areastr[0].area_name
    }
    //for可以加上
    for (let index = 0; index < data.length; index++) {
   
        let codeStr = await forFun(data[index])
        data[index].codeStr = codeStr
        console.log(data[index], 'data[index]');
    }
    res.send(endMassage(data))
});

在这里插入图片描述
在这里插入图片描述
很直接的完成了我们的需求,这源于for循环的机制流程:
在这里插入图片描述
首先判断1这个条件,执行2中的代码块,只有执行将await执行完,在执行3,以此循环。

目录
相关文章
|
4月前
|
编译器 数据处理 C#
C#中的异步流:使用IAsyncEnumerable<T>和await foreach实现异步数据迭代
【1月更文挑战第10天】本文介绍了C#中异步流的概念,并通过使用IAsyncEnumerable<T>接口和await foreach语句,详细阐述了如何异步地迭代数据流。异步流为处理大量数据或需要流式处理数据的场景提供了一种高效且非阻塞性的方法,使得开发者能够更优雅地处理并发和数据流问题。
|
前端开发 JavaScript
😲完了完了,forEach异步执行,怎么后面的先完成了!?
代码review,业务里的代码千奇百怪,到底还能遇到什么呢?oh no,真的有人在forEach里用异步调用!
481 0
|
3月前
|
前端开发 JavaScript 数据处理
在JavaScript中,异步函数是指那些不会立即执行完毕,而是会在未来的某个时间点(比如某个操作完成后,或者某个事件触发后)才完成其执行的函数
【6月更文挑战第15天】JavaScript中的异步函数用于处理非同步任务,如网络请求或定时操作。它们使用回调、Promise或async/await。
42 7
|
2月前
|
数据采集 JavaScript 前端开发
NodeJS技巧:在循环中管理异步函数的执行次数
在Node.js网络爬虫开发中,管理异步函数执行次数是关键。利用Promise.all、async/await或async库能优雅地控制并发。示例展示如何用async/await配合代理IP抓取数据,避免触发反爬策略。在循环中,每个异步请求只执行一次,保证请求有序进行,提高爬虫的稳定性和效率。通过正确的方法,可以有效应对网络爬虫的挑战。
NodeJS技巧:在循环中管理异步函数的执行次数
|
24天前
|
JavaScript 前端开发
深入理解Node.js事件循环及其对后端性能的影响
【8月更文挑战第31天】 本文将带你一探Node.js的核心概念—事件循环,揭示其工作原理及如何影响后端应用的性能。我们将从基础的事件驱动模型出发,通过代码示例和性能分析,展示如何有效利用事件循环来提升应用响应速度和处理能力。
|
2月前
|
Web App开发 JavaScript 前端开发
谁说forEach不支持异步代码,只是你拿不到异步结果而已
JavaScript 的 `forEach` 不直接支持异步操作,但可以在回调中使用 `async/await`。虽然 `forEach` 不会等待 `await`,异步代码仍会执行。MDN 文档指出 `forEach` 预期同步回调。ECMAScript 规范和 V8 源码显示 `forEach` 基于 for 循环实现,不返回 Promise。通过 `setTimeout` 可观察到异步操作完成。与 `map` 不同,`forEach` 不适合处理异步序列,常需转换为 `Promise.all` 结合 `map` 的方式。
38 11
|
2月前
|
JavaScript 前端开发 API
js 运行机制(含异步机制、同步任务、异步任务、宏任务、微任务、Event Loop)
js 运行机制(含异步机制、同步任务、异步任务、宏任务、微任务、Event Loop)
30 0
|
3月前
|
JavaScript 前端开发
在vue中循环中调用接口-promise.all();按顺序执行异步处理
在vue中循环中调用接口-promise.all();按顺序执行异步处理
|
4月前
|
开发框架 JavaScript 前端开发
描述JavaScript事件循环机制,并举例说明在游戏循环更新中的应用。
JavaScript的事件循环机制是单线程处理异步操作的关键,由调用栈、事件队列和Web APIs构成。调用栈执行函数,遇到异步操作时交给Web APIs,完成后回调函数进入事件队列。当调用栈空时,事件循环取队列中的任务执行。在游戏开发中,事件循环驱动游戏循环更新,包括输入处理、逻辑更新和渲染。示例代码展示了如何模拟游戏循环,实际开发中常用框架提供更高级别的抽象。
31 1
|
4月前
|
前端开发 JavaScript API
Promise.all() 的原理与实战:简化异步逻辑的不二选择
Promise.all() 的原理与实战:简化异步逻辑的不二选择
Promise.all() 的原理与实战:简化异步逻辑的不二选择