如何使用 Node.js return 从一个模块到另一个模块的异步数据库查询结果?

How do I return an asynchronous DB query result from one module to another using Node.js?

我是 Node 的新手,我正在尝试遵循 Udemy API 课程中的模式。 API 的结构是利用路由、控制器和服务模块进行流。数据库查询将 运行 作为服务,它们应该从控制器调用。

我需要 运行 一系列数据库查询来生成一个列表(在这个例子中我只显示了 6 个查询中的 2 个)。我在我的函数中使用 async/await 运行 宁这些。查询工作正常。当我尝试在流程结束时将 return 'batch result'(所有查询的结果)发送给控制器时,我的问题就出现了。我得到 Promise { <pending> }。我已经尝试了很多东西,但我无法结束从我的控制器模块访问最终结果的承诺——我只能从我的服务模块访问它。

这是我调用函数的控制器模块 (groups.controller.js) 中的代码:

const groupsService = require('../services/groups.service');

exports.propertyList = (req, res, next) => {

    const uid = req.body.uid;

    const batchResponse = groupsService.batchQuery(uid, res);
    console.log(batchResponse);

}

这是我的服务模块 (groups.services.js) 中的代码,我在其中 运行 查询:

const mysql = require('mysql2');
const dbAsync = require("../config/db.config");

async function batchQuery(uid, res) {

    var Q1;
    var Q2;

    var uid = uid * -1;

    const pool = mysql.createPool(dbAsync.dbAsync);
    const promisePool = pool.promise();

    try {
        Q1 = await promisePool.query('SELECT PropertyID FROM GroupMembership WHERE GroupID = ?', [uid]);
        Q2 = await promisePool.query('SELECT SubGroupID FROM GroupMembership WHERE GroupID = ? AND PropertyID = ?', [uid, 0]);
    }
    catch(error) {
        console.log(error);
        res.status(401).send('Server error');
        return error;
    }
    finally {
        const batchResponse = {
            Q1: Q1[0],
            Q2: Q2[0]
        }

        console.log('Q1: '+ Q1[0][0].PropertyID + ', Q2: ' + Q2[0][0].SubGroupID);
        res.status(200).send(batchResponse);
        return batchResponse;
    }
}

module.exports = {batchQuery};

当我通过 postman 发送 post 时,我得到了预期的查询结果(如下)。但是,如果我将 res 放入我的服务模块,我只能让它工作。

{
    "Q1": [
        {
            "PropertyID": 0
        }
    ],
    "Q2": [
        {
            "SubGroupID": 397
        }
    ]
}

有没有办法结束此模式中的承诺和 return 所需的批处理响应?谢谢。

编辑:添加@traynor 提供的代码更新。

新控制器:

const groupsService = require('../services/groups.service');

exports.propertyList = async (req, res, next) => {

    const uid = req.body.uid;

    let batchResponse;
    try {
        batchResponse = await groupsService.batchQuery(uid);
        console.log(batchResponse);
        return res.status(200).send(batchResponse);
    } catch(error) {
        console.log('Error: ' + error);
        return res.status(401).send('Server error');
    }
}

新服务:

const mysql = require('mysql2');
const dbAsync = require("../config/db.config");

function batchQuery(uid) {
    
    return new Promise((resolve, reject) => {

        var Q1;
        var Q2;

        var uid = uid * -1;

        const pool = mysql.createPool(dbAsync.dbAsync);
        const promisePool = pool.promise();

        try {
            Q1 = await promisePool.query('SELECT PropertyID FROM GroupMembership WHERE GroupID = ?', [uid]);
            Q2 = await promisePool.query('SELECT SubGroupID FROM GroupMembership WHERE GroupID = ? AND PropertyID = ?', [uid, 0]);
        } catch(error) {
            console.log(error);
            reject(error);
        } finally {
            const batchResponse = {
                Q1: Q1[0],
                Q2: Q2[0]
            }
            console.log('Q1: '+ Q1[0][0].PropertyID + ', Q2: ' + Q2[0][0].SubGroupID);
            resolve(batchResponse);
        }
    })
}

module.exports = {batchQuery};

服务现在return承诺,它也在处理响应而不是控制器。

从服务

到 return,你需要 promisify 服务:return 一个在你获取数据库数据或出错时解决的承诺,然后你还需要等待服务,这它包含在 try/catch 中用于错误处理。

完成后,处理来自控制器的响应:

服务:

function batchQuery(uid) {

    return new Promise(async (resolve, reject) => {

        var Q1;
        var Q2;
        //...

        try {
            //...
        } catch (error) {
            console.log(error);
            reject(error);
        } finally {
            const batchResponse = {
                Q1: Q1[0],
                Q2: Q2[0]
            }
            console.log('Q1: ' + Q1[0][0].PropertyID + ', Q2: ' + Q2[0][0].SubGroupID);

            resolve(batchResponse);
        }
    });

控制器:

exports.propertyList = async (req, res, next) => {

    const uid = req.body.uid;

    let batchResponse;
    try {
        batchResponse = await groupsService.batchQuery(uid);
        console.log(batchResponse);
        res.status(200).send(batchResponse);
    } catch(error) {
        return res.status(401).send('Server error');
    }

}