You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeJS异步循环中SQL查询结果无法正确存入数组问题排查

Node.js异步SQL查询循环中await不生效的问题解决

问题描述

本人习惯使用Java,近期启动了一个NodeJS项目,遇到异步逻辑相关问题。需要编写一个函数,循环执行SQL查询(每次迭代修改参数)并将结果存入数组。定义了数组变量let FINAL = [],尝试在每次查询返回数据时将结果push进去,但发现最后一行console.log("RESULT : " + FINAL)比循环内的console.log先执行,即使添加了await也无法解决问题。

代码如下:

const fluxAccesParPeriode = async (req, res) => {
    try {
        const db = res.locals.db;
        const {date_debut, date_fin} = req.body;

        if (!date_debut || !date_fin) {
            res.status(400).json({error: 'One or more informations are missing.'});
            return;
        }

        // SQL
        const queryText = "SELECT COUNT(id_pointage) AS nbreAcces FROM pointage_adherents PA, adherents A WHERE PA.id_adherent=A.id_adherent AND date BETWEEN ? AND ? AND heure_entree BETWEEN ? AND ?";

        let FINAL = [];

        for (let i = 0; i < 24; i += 3) {
            let heure_debut = i + ":00:00";
            let heure_fin = (i + 3) + ":00:00";

            await db.execute(queryText,
                [date_debut, date_fin, heure_debut, heure_fin],
                (err, results) => {
                    if (err) {
                        console.error('Error executing SQL query:', err);
                        res.status(500).json({error: 'Internal Server Error'});
                        return;
                    }

                    console.log(heure_debut + "  /   " + heure_fin + "  /  " + results[0]["nbreAcces"]);

                    FINAL.push({heure_debut: heure_debut, heure_fin: heure_fin, result: results[0]["nbreAcces"]});
                });
        }

        console.log("RESULT : " + FINAL);

        if (FINAL.length > 0) {
            res.status(200).json(FINAL);
        } else {
            res.status(400).json({error: 'Error while executing your query: fluxAccesParPeriode'});
        }

    } catch (error) {
        console.error(error.stack);
        res.status(500).json({message: 'Erreur lors de l\'exécution de la requête'});
    }
}

问题原因

核心问题是**await只对返回Promise的函数生效**。你当前使用的db.execute是回调风格的API——它不会返回Promise,而是通过第三个参数的回调函数处理异步结果。所以你加的await根本没有等待查询完成,循环会直接走完,此时回调函数还没执行,FINAL数组自然是空的,最后一行的console.log也就先输出了。

解决方案

把回调风格的db.execute转换成Promise风格,这样await才能正确等待异步操作完成。可以用Node.js内置的util.promisify工具,或者直接使用数据库库提供的Promise版本方法。

修改后的代码示例

const util = require('util'); // 引入util模块
const fluxAccesParPeriode = async (req, res) => {
    try {
        const db = res.locals.db;
        // 将回调风格的execute转为Promise风格,bind绑定db上下文
        const executeQuery = util.promisify(db.execute).bind(db);
        const {date_debut, date_fin} = req.body;

        if (!date_debut || !date_fin) {
            res.status(400).json({error: 'One or more informations are missing.'});
            return;
        }

        const queryText = "SELECT COUNT(id_pointage) AS nbreAcces FROM pointage_adherents PA, adherents A WHERE PA.id_adherent=A.id_adherent AND date BETWEEN ? AND ? AND heure_entree BETWEEN ? AND ?";

        let FINAL = [];

        for (let i = 0; i < 24; i += 3) {
            let heure_debut = i + ":00:00";
            let heure_fin = (i + 3) + ":00:00";

            // 用await等待Promise完成,直接获取结果
            const results = await executeQuery(queryText, [date_debut, date_fin, heure_debut, heure_fin]);
            console.log(heure_debut + "  /   " + heure_fin + "  /  " + results[0]["nbreAcces"]);
            FINAL.push({heure_debut: heure_debut, heure_fin: heure_fin, result: results[0]["nbreAcces"]});
        }

        console.log("RESULT : ", FINAL); // 改用逗号输出,避免数组转字符串显示异常

        if (FINAL.length > 0) {
            res.status(200).json(FINAL);
        } else {
            res.status(400).json({error: 'Error while executing your query: fluxAccesParPeriode'});
        }

    } catch (error) {
        console.error(error.stack);
        res.status(500).json({message: 'Erreur lors de l\'exécution de la requête'});
    }
}

额外说明

  1. 如果你的数据库库本身支持Promise(比如mysql2/promise),可以直接使用Promise版本的连接,这样就不需要util.promisify,直接调用db.execute就能返回Promise。
  2. 原代码中在回调里调用res.status(500)可能会出现重复响应的问题,改成Promise+await后,错误会被外层的try/catch统一捕获,处理响应更安全。

内容的提问来源于stack exchange,提问作者Abderaouf Boucenna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 11:15:15