2014-06-15 3 views
5

Мне было интересно, как лучше всего обрабатывать вложенные mysql-запросы - nodejs.Узел Mysql async несколько запросов

Так что-то вроде этого:

connection.query("SELECT * FROM blogs ORDER BY time DESC", function(err, blogs, fields) { 

    for (blog in blogs) { 

     connection.query("SELECT * FROM tags WHERE blog_id='blog.id' ", function(err, tags, fields) { 

     blog.tags = tags 

    }); 

    } 

    res.send(blogs) 

}); 

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

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

Thx!

+0

Это была бы хорошая возможность начать использовать библиотеку обещаний, такую ​​как [Q] (https://github.com/kriskowal/q), в этом случае это ['Q.spread'] (https://github.com/kriskowal/q#combination) (или, возможно, [эти примеры сокращения] (https://github.com/kriskowal/q#sequences) – Bojangles

ответ

3

Таким образом, вам нужно подождать, пока все обратные вызовы вернутся, прежде чем отправлять ответ. Если мы будем игнорировать обработку ошибок и пустые результаты для простоты это можно сделать подобное:

var callback = function(blogs) { 
    res.send(blogs); 
} 

connection.query("SELECT * FROM blogs ORDER BY time DESC", function(err, blogs, fields) { 
    var pending = blogs.length; 

    for (blog in blogs) { 

     connection.query("SELECT * FROM tags WHERE blog_id='blog.id' ", function(err, tags, fields) { 
     blog.tags = tags; 

     if (0 === --pending) { 
      callback(blogs); 
     } 
    }); 
    } 
}); 

обещаниями, посмотрите в функцию Promise.all которая возвращает новое обещание. Эти обещания разрешаются, когда все обещания, переданные ему в массиве, разрешаются. С помощью библиотеки Q должно быть что-то вроде:

var getTags = function(blog) { 
    var deferred = Q.defer(); 
    connection.query("SELECT * FROM tags WHERE blog_id='blog.id' ", function(err, tags, fields) { 
     blog.tags = tags; 
     deferred.resolve(); 
    }); 
    return deferred.promise; 
} 

var promises = blogs.map(getTags(blog)); 

Q.all(promises).then(res.send(blogs)); 
2

Вы можете попробовать что-то вроде этого;

connection.query("SELECT * FROM blogs ORDER BY time DESC", fetchedBlogs); 

function fetchedBlogs(err, blogs, fields) { 

    if (err || !blogs || !blogs.length) { 
     // an error occurred or no blogs available 
     // handle error or send empty blog array 
     return res.send(); 
    } 

    var count = blogs.length; 

    (function iterate(i) { 
      if (i === count) { 
       // all blogs processed! 
       return res.send(blogs); 
      } 

      var blog = blogs[i]; 

      connection.query("SELECT * FROM tags WHERE blog_id='" + blog.id + 
       "'", fetchedTags); 

      function fetchedTags(err, tags, fields) { 
       blog.tags = tags; 
       iterate(i+1); 
      }); 
    })(0); 
} 

Надеюсь, это поможет.

+0

Почему этот ответ подавлен? Я согласен, что идеальным решением этой проблемы будет выборка обоих данных в одном запросе. Это решение работает, если нужны два запроса, этот фрагмент также использует аккуратный способ обработки обратных вызовов в цикле без использования библиотеки управления потоком, такой как async/prom/etc. – vmx

3

Вы можете использовать async.series модуль (перебрать queries`)

async.eachSeries(blogs, 
       function (query, callback) { 

        connection.query(blogs.blog, "SELECT * FROM tags WHERE blog_id='blog.id'" , function (err, result) { 
         if (err) { 

          //throw err; 
          callback(err, null); 
          return; 

         } else { 
          console.log('Query executed successfully'); 
          blogs.blog.tags = tags; 
         } 
         callback(null, blogs.blog); 

        }); 

       }, 

       function finalCallback(err, results) { 

          return callback(null, results); 
         }); 
        } 
       }); 

     }); 



    });` 

Вы можете улучшить это с помощью функции и query.on (для обработки каждой строки)

Смежные вопросы