首页 > 解决方案 > Node.JS 等待每个并行 mysql 查询完成

问题描述

我需要以下方面的帮助:我有4 个 MySQL 查询,我希望并行运行,但在继续主函数之前必须完成所有查询;这四个查询获取数据的不同部分(它们的结构不同并访问不同的表),然后在 main 函数中使用。也就是说,我使用了 async.parallel(甚至尝试添加await关键字),但在async.parallel中调用最终回调之前仍然结束。我什至考虑过集群和工作线程,但是每个查询函数都彼此不同。

async.parallel中的函数是 MySQL 连接查询,形式如下:

connection.query(q, function(err, res) { 
   if(err) { 
      callback(err, []) 
   } else { 
     // do something
     callback(null, res) 
   } 
})

每个函数都有不同的形状,为了简洁起见,这只是一个简化的形式。函数示例:

async main_function() {
  await async.parallel({
  "1": function(callback) { conn.query(q1, function(...) { console.log("1"); callback(null, 1) }) },
  "2": function(callback) { conn.query(q2, function(...) { console.log("2"); callback(null, 2) }) },
  "3": function(callback) { conn.query(q3, function(...) { console.log("3"); callback(null, 3) }) },
  "4:" function(callback) { conn.query(q4, function(...) { console.log("4"); callback(null, 4) }) }
  }, function(err, results) { /*final callback; do something*/ console.log("Finished"); })
  console.log("Continuing");

  //continue
}

预期输出:

3
2
4
1
Finished
Continuing

实际输出:

Continuing
3
2
4
1
Finished

如果还有其他方法(即使没有 async.parallel),我也愿意接受。稍后我可能会在函数和程序的其他部分中使用多个不同的并行 MySQL 查询,因此使用 async.parallel 之类的参数化形式非常有用。

Javascript 是单线程的意味着诸如“检查查询是否完成的 while 循环”之类的解决方案不起作用。这个 main_function 会经常被调用,所以分叉会导致问题。

编辑:Jakub 的解决方案相当简单,因为在我的程序中如下所示:

async main_function() {

await Promise.all([
    new Promise((resolve, reject) => {
        connection.query(q1 , function (error, result) {
            if (error != null) {
                console.log("mysql query error", error);
                return reject(error);
            } else {
                console.log("1");
                resolve(result);
            }
        })
    }),
    new Promise((resolve, reject) => {
        connection.query(q1 , function (error, result) {
            if (error != null) {
                console.log("mysql query error", error);
                return reject(error);
            } else {
                console.log("2");
                resolve(result);
            }
        })
    }), ... // Two more times
]).then((values) => {
    data[0] = values[0];
    data[1] = values[1];
    data[2] = values[2];
    data[3] = values[3]; 
}).catch(function (err) { console.log(err); });

console.log("Continuing"); //continue
}

这现在非常粗糙,如果有人想为未来的程序员建议更清洁/更好的解决方案,请继续。

标签: javascriptmysqlnode.jsasynchronousparallel-processing

解决方案


这些查询函数是基于回调的(从您的代码来看),您可以对它们进行承诺:

import { promisify } from 'utils';

async main_function() {
    const res = await Promise.all([
        promisify(conn.query)(q1),
        promisify(conn.query)(q2),
        // all your other queries 
    ]);
    console.log("Continuing");

    //continue
}  

推荐阅读