【问题标题】:How to add MySQL query results from a loop in Nodejs?如何从 Nodejs 中的循环中添加 MySQL 查询结果?
【发布时间】:2021-01-05 03:36:44
【问题描述】:

基本上,我有一个带有字符串键和值的对象(例如 {"michigan":"minnesota"})。我正在尝试遍历所有这些键值对并从我的数据库中进行查询,并将结果添加到列表中,然后将其返回到前端。

var return_list = []

        Object.keys(obj).forEach(function(key){
            const state1 = key;
            const state2 = obj[key];

            const sql_select = 'SELECT column1,column2 from database WHERE state = ? OR state=?';
        
            db.query(sql_select,[state1,state2], (err,result) => {
                
                return_list.push(result);
            });
        })

这就是我最简单的说法,并且想将 return_list 发送回前端。我遇到的问题是我可以 console.log 在 db.query 调用中记录结果,但我不能将结果推送到列表或在查询之外的任何地方调用它。我对前端和后端开发都很陌生,所以任何可能的想法肯定会有所帮助!

【问题讨论】:

  • 我能知道这个函数运行的上下文吗?因为通常这是一个后端函数,并且可以有简单的响应方法来响应前端请求的东西

标签: javascript mysql node.js


【解决方案1】:

问题是 forEach 返回 void。
因此,您不能等待异步代码运行后再返回。
当我们处理一系列承诺时,例如数据库查询(如您的情况)或 API 调用,我们应该等待它们中的每一个都被执行。
那就是我们使用Promise.all

尝试这样做:

const queryResults = await Promise.all(
   Object.keys(obj).map(async (key) => {
    const state1 = key;
    const state2 = obj[key];

    const sql_select = 'SELECT column1,column2 from database WHERE state = ? OR state=?';

    return new Promise((resolve, reject) => 
      db.query(sql_select,[state1,state2], (err, result) => {
        if (err) 
          return reject(err)
        else
          return resolve(result)
      })
    )
  })
)
console.log('queryResults', queryResults)
// now you give this queryResults back to your FE

重新开始的小技巧:

  • 永远不要使用 var,尝试始终使用 const,或者如果需要,让我们使用。
  • 尝试始终使用arrow functions() => {...})而不是常规函数(function () {...}),很难预测最后一个使用的是哪个范围

【讨论】:

  • Await 需要在异步函数中。我可以把它放在一个异步函数中,然后调用它吗?另外,感谢其他提示。我一直只使用 const 除了在上面我使用 var haha​​ 的代码中
  • 是的,您当然可以将这段代码分离到一个函数 ant 中,然后调用它。使用 express 您可以执行以下操作:router.get('myEndpoint', (req, res) => myFunction().then(myQueryResult => res.status(200).json(myQueryResult))
  • 再次感谢,它有效!我将上面的代码放在一个异步函数中并返回了 queryResults。
【解决方案2】:

问题是因为数据库事务不是即时的,所以你需要使用 promises 或 async-await。

使用异步等待会是这样的(未经测试),

async function get_return_list () {
    var return_list = []

    Object.keys(obj).forEach(function(key){
        const state1 = key;
        const state2 = obj[key];
    
        const sql_select = 'SELECT column1,column2 from database WHERE state = ? OR state=?';
    
         await db.query(sql_select,[state1,state2], (err,result) => {
            
            return_list.push(result);
        });
    })

    return return_list
} 

查看详情:https://eloquentjavascript.net/11_async.html

【讨论】:

  • 感谢您的回复。我目前正在尝试不同的变体,但在返回之前调用时,上面的 return_list 仍然是一个空列表。我认为这是正确的方向,您有更多的见解吗?我还必须将功能更改为异步,但它不起作用
【解决方案3】:

首先,确保您使用的是来自 npm 的 mysql2。其中提供了mysql的异步方法。 其次,请注意,当您查询SELECT 时,您不会首先获得“真实”结果。假设你得到result,那么,“真实”结果保存在result[0]中。

(async () => {
    const promiseArr = [];

    for (const key of Object.keys(yourOBJ)) {
        const state1 = key;
        const state2 = yourOBJ[key];
        const sql_select = 'SELECT column1,column2 from database WHERE state = ? OR state=?';

        promiseArr.push(db.query(sql_select, [state1, state2]));
    }

    let results;

    try {
        results = await Promise.all(promiseArr);
    } catch (e) {
        throw '...';
    }

    const return_list = results.reduce((finalArray, item) => {
        finalArray = [
            ...finalArray,
            ...item[0],
        ]
    }, []);
})();

【讨论】:

    猜你喜欢
    • 2020-08-20
    • 2017-10-07
    • 2015-07-26
    • 2021-02-15
    • 2017-10-07
    • 1970-01-01
    • 2017-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多