Выполните два или более запросов в одном запросе, используя node-mysql и ExpressJS

tl; dr: каков правильный способ обработки двух или более асинхронных запросов к базе данных MySQL с помощью node-mysql с ExpressJS?

Я использую ExpressJS с node-mysql для выполнения двух отдельных, несвязанных запросов к базе данных MySQL. Поскольку ответы асинхронны, я вложил запросы, что означает, что они в конечном итоге происходят один за другим.

Это кажется уродливым, медленным и вообще плохим подходом, особенно если я должен был добавить третий или четвертый вопрос.

var mysql      = require('mysql');
var credentials = {...}

router.get('/api/url/', function (req, res) {
    return_data = {}
    var connection = mysql.createConnection(credentials);
    query1 = "SELECT column1 FROM table1 WHERE column2 = 'foo'";
    query2 = "SELECT column1 FROM table2 WHERE column2 = 'bar'";
    connection.query(query1, {}, function(err, results) {
        return_data.table1 = results;
        connection.query(query2, {}, function(err, results) {
            return_data.table2 = results;
            connection.end();
            res.send(return_data);
        });
    });
});

3 ответов


имейте в виду, что для параллельного выполнения запросов вам придется использовать пул соединений. Только один запрос может быть запущен одновременно на соединении mysql. См.https://github.com/felixge/node-mysql/#pooling-connections для примеров.

ответ Remyp должен быть изменен следующим образом:

var mysql      = require('mysql');
var async      = require('async');
var credentials = {connectionLimit: 10,...}

router.get('/api/url/', function (req, res) {
    var pool = mysql.createPool(credentials);
    var query1 = "SELECT column1 FROM table1 WHERE column2 = 'foo'";
    var query2 = "SELECT column1 FROM table2 WHERE column2 = 'bar'";

    var return_data = {};

    async.parallel([
       function(parallel_done) {
           pool.query(query1, {}, function(err, results) {
               if (err) return parallel_done(err);
               return_data.table1 = results;
               parallel_done();
           });
       },
       function(parallel_done) {
           pool.query(query2, {}, function(err, results) {
               if (err) return parallel_done(err);
               return_data.table2 = results;
               parallel_done();
           });
       }
    ], function(err) {
         if (err) console.log(err);
         pool.end();
         res.send(return_data);
    });
});

Я бы прокомментировал его сообщение, но у меня еще нет представителя, чтобы сделать это, так что опубликовано в качестве ответа.


Это отличный кандидат для использования асинхронные. Вот один из способов вы могли бы преобразовать это через это:

var mysql      = require('mysql');
var async      = require('async');
var credentials = {...}

router.get('/api/url/', function (req, res) {
    var connection = mysql.createConnection(credentials);
    var query1 = "SELECT column1 FROM table1 WHERE column2 = 'foo'";
    var query2 = "SELECT column1 FROM table2 WHERE column2 = 'bar'";

    var return_data = {};

    async.parallel([
       function(parallel_done) {
           connection.query(query1, {}, function(err, results) {
               if (err) return parallel_done(err);
               return_data.table1 = results;
               parallel_done();
           });
       },
       function(parallel_done) {
           connection.query(query2, {}, function(err, results) {
               if (err) return parallel_done(err);
               return_data.table2 = results;
               parallel_done();
           });
       }
    ], function(err) {
         if (err) console.log(err);
         connection.end();
         res.send(return_data);
    });
});

очевидно, что есть более элегантные способы сделать это, но это хорошо демонстрирует концепции. Два запроса выполняются параллельно, затем, как только они оба завершены, мы вызываем последнюю функцию, чтобы закрыть соединение и вернуть данные.

Если есть ошибка, мы сразу перейдем к последней функции и вызовем ее, которая будет вероятно, это приведет к странному поведению при отправке return_data, поэтому я бы не рекомендовал использовать этот код как есть.

Если вы хотите узнать больше, проверить асинхронный документации.


С в этой статье:

в целях безопасности по умолчанию выполнение нескольких запросов операторов отключено. Чтобы использовать несколько запросов операторов, вы должны сначала включить его при создании соединения, как показано ниже.

var connection =  mysql.createConnection( { multipleStatements: true } );

Как только он включен, вы можете выполнить несколько запросов заявление, как показано ниже в подключение.запрос.

connection.query('select column1; select column2; select column3;',    
function(err, result){
  if(err){
      throw err;
  }else{
      console.log(result[0]);       // Column1 as a result
      console.log(result[1]);       // Column2 as a result
      console.log(result[2]);       // Column3 as a result
  }
});