Node.js 다중 쿼리 결과 처리 방법

조회수 4862회

node.js, express 를 이용 중 입니다.

mysql 연동해서 db 결과를 변수 값에 넣고, render 쪽에 보내주려고 합니다.

그런데 전역변수를 시도하려 global.score 로 표기까지 해봤는데, 결과는 아래와 같이 쿼리 결과는 하나도 없이 나와서 질문드립니다.

node.js 는 한 3일정도 밖에 접하지 못해서 콜백 사용법이 미숙하여 질문드립니다. 어떻게 쿼리 결과를 전부 불러올 수 있는지 알려주시길 부탁드립니다.

[결과]

)]}', {"scoredboard" : [}

[소스코드]

var express = require('express');
var router = express.Router();
//db - mysql
var mysql = require('mysql');
var dbconfig = require('../dbconfig.js');
var db = dbconfig.database;
var connection=mysql.createConnection({
   host:db.host,
   port:db.port,
   user:db.user,
   password:db.password,
   database:db.database
});


/* GET home page. */
router.get('/', function(req, res, next) {
  /*
{"scoreboard": [{"tid": 68, "position": 1, "score": 200, "name": "A", "history": [{"score": 200, "when": "2016-04-01T17:17:42+00:00"}, {"score": 150, "when": "2016-03-28T17:19:04+00:00"}, {"score": 50, "when": "2016-03-27T17:24:33+00:00"}, {"score": 10, "when": "2016-03-23T17:32:48+00:00"}, {"score": 5, "when": "2016-03-22T17:24:33+00:00"}]}, {"tid": 3, "position": 2, "score": 0, "name": "B", "history": [{"score": 0, "when": "2016-03-23T17:18:26+00:00"}]}
*/
  global.scoreboard = '{\"scoredboard\" : [';
  var position = connection.query('select tid, score, name from teams order by (score+0);', function(err, rows_tid)
  {
      if(err)
      {
          console.error(err);
          throws(err);
      }
      else
      {
          for(var i in rows_tid)
          {
              global.scoreboard = global.scoreboard + '{\"tid\": ' + rows_tid[i].tid + ', \"position\": ' + i + ', \"score\": ' + rows_tid[i].score + ', \"name\": \"' + rows_tid[i].name + '\", \"history\": [';
              var query = connection.query('select score,DATE_FORMAT(wh, \'%Y-%m-%dT%T\') as wh from scoreboard where tid = ? order by wh',rows_tid[i].tid, function(err, rows)
              {
                  if(err)
                  {
                      console.error(err);
                      throws(err);
                  }
                  else
                  {
                      for(var j in rows)
                      {
                          global.scoreboard = global.scoreboard + '{\"score\": ' + rows[j].score + ', \"when\": ' + rows[j].wh + '}';
                          if(j != rows.length-1)
                          {
                              global.scoreboard = global.scoreboard + ', ';
                          };
                      };
                  };
              });
              global.scoreboard = global.scoreboard + ']}';
              if (i != rows_tid.length-1)
              {
                  global.scoreboard = global.scoreboard + ', ';
              }
          };
      };
  });
  global.scoreboard = global.scoreboard + '}';
  res.render('scoreboard', {scoreboard:global.scoreboard});
});

module.exports = router;
  • (•́ ✖ •̀)
    알 수 없는 사용자

1 답변

  • 위 코드에서 빈 결과가 나오는 이유는 res.render 함수가 호출되는 시점에 global.scoreboard 변수가 아직 준비되지 않았기 때문입니다.

    router.get으로 입력된 요청은 res.render 함수가 호출되는 동시에 종료됩니다.

    위 코드에 문제는 connectiion.query의 결과를 기다리지 않고 res.render 함수를 호출하기 때문입니다.

    connectiion.query는 비동기 함수이기 때문에 해당 라인에서 코드가 멈춰서 결과를 기다리지 않고 계속 다음 라인으로 진행됩니다. 이후 실행 결과는 callback 함수를 통해 전달됩니다.

    따라서 문제를 해결하려면 connection.query함수로 전달되는 callback 함수(function(err, rows_tid) 안쪽에서 전달된 쿼리 결과(rows_tid)를 사용해서 res.render함수를 호출해 줘야 합니다.

    위 이야기가 다 이해 되셨다면 문제는 모두 해결된 셈입니다.

    위 코드에서는 추가적으로 약간 더 복잡한 부분이 있는데 connection.query가 중첩되서 사용된 점입니다. 이런 부분은 손으로 직접 짜셔서 해결하실 수도 있지만 보통 async모듈이나 promise등을 이용해서 해결합니다.

    Node.js에서 가장 확실한 비동기 해결 방법은 코루틴을 사용하는 것인데 위 모듈 사용에 익숙해 지시면 한번 활용해 보시기를 추천 드립니다.

    p.s: 비동기 문제를 해결하는데 전역변수는 필요하지 않습니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • (•́ ✖ •̀)
      알 수 없는 사용자
    • 감사합니다. 검색중에 async 모듈은 본적있었는데 모듈을 또 사용해야하나 하고 코드를 위처럼 짜봤는데... 비동기를 생각하지 못했네요. Async 를 사용해 보도록 하겠습니다. :) 알 수 없는 사용자 2016.4.11 08:42

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)