2013-09-25 3 views
2

У меня есть код сервера.Длинный опрос с Node.js и ajax

var http = require('http'); 
var mysql = require('mysql'); 
var querystring = require('request'); 
var util = require('util'); 
var url = require('url'); 

var singer_name; 
var currentmodif, lastmodif; 
var requests=[]; 
var response; 

var connection = mysql.createConnection({ 
    host  : 'localhost', 
    user  : 'someone', 
    password : 'xxxxxxx', 
    database : 'rest', //mysql database to work with (optional) 
}); 
connection.connect(); //connect to mysql 

connection.query('SELECT * FROM musics WHERE id=1', function(err, rows, fields) { 
    if (err) throw err; 

    singer_name=rows[0].singer_name; 
    currentmodif=rows[0].time_added; 
}); 


http.createServer(function (req, res) { 
    console.log('request received'); 

    requests.push({ 
     response: res, 
     timestamp: new Date().getTime() 
    }); 

    if(req.method=='GET'){ 
     var url_parts = url.parse(req.url,true); 
     lastmodif = url_parts.query.timestamp; 
    } 

    //check_update(req, res); 

}).listen(9000); 


setInterval(function() { 

    var expiration = new Date().getTime() - 30000; 

    for (var i = requests.length - 1; i >= 0; i--) { 
     //console.log("Request timestamp: "+requests[i].timestamp+" Expiration : "+expiration); 
     response = requests[i].response; 
     if (requests[i].timestamp < expiration) { 
      console.log("The condition is met"); 
      response.writeHead(200, { 
      'Content-Type' : 'text/plain', 
      'Access-Control-Allow-Origin' : '*' 
      }); 

      // return response 
      response.write('_testcb(\'ok\')', 'utf8'); 
      response.end(); 
      //break; 
     } 
    } 

    connection.query('SELECT * FROM musics WHERE id=1', function(err, rows, fields) { 
     if (err) throw err; 
     currentmodif=rows[0].time_added;   
      //console.log("currentmodif: "+currentmodif+" lastmodif: "+lastmodif); 
     if (currentmodif > lastmodif){ 
      singer_name=rows[0].singer_name; 
      var _arrays = {'singer_name': singer_name, 'time': currentmodif} 
      var data = "_testcb"+"("+JSON.stringify(_arrays)+")"; 
      response.writeHead(200, { 
      'Content-Type' : 'text/plain', 
      'Access-Control-Allow-Origin' : '*' 
      }); 
      if (response.end(data)) 
      console.log("Response successfully sent"); 
      //return false; 
     } 

    }); 
}, 2000); 

и код клиента:

<html> 
<head> 
    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> 
    <title>Node.js Ajax test</title> 
</head> 
<body> 

</body> 
<script> 
var timestamp = "1380020402"; 
function callNode() { 

var time = "1380020402"; 
    $.ajax({ 
     url: 'http://xx.xxx.xx.xxx:9000/', 
     dataType: "jsonp", 
     data: {"timestamp":timestamp}, 
     type: 'POST', 
     jsonpCallback: "_testcb", 
     cache: false, 
     timeout: 35000, 
     success: function(response, code, xhr) { 
      if ('ok' == response) { 
       callNode(); 
       return false; 
      } 

      console.log(response); 

      timestamp = response.time; 
      // make new call 
      callNode(); 
     }, 
     error: function(jqXHR, textStatus, errorThrown) { 
      console.log('error ' + textStatus + " " + errorThrown); 
     } 
    }); 
} 
$(function() { 
    callNode(); 
}); 
</script> 
</html> 

Я пытаюсь сделать длинный опрос. Поэтому, пока данные в базе данных не будут обновлены, ответ на запрос ajax должен быть приостановлен, но вышеуказанный код не работает. Я делаю запрос ajax из другого домена и, следовательно, используя jsonp.

Точная проблема заключается в том, что в настоящее время при изменении данных в базе данных ответ не отправляется. Он работает время от времени, но он не всегда надежный.

Другая проблема заключается в том, что блок кода для тайм-аута не работает. Если запрос составляет 30 секунд, тогда необходимо отправить пустой ответ, чтобы избежать таймаута из ajax.

Если кто-то может помочь, я был бы признателен.

Cheers.

ответ

5

Я понял это. Измененный код, который работает, как показано ниже:

стороны клиента:

<html> 
<head> 
    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> 
    <title>Node.js Ajax test</title> 
</head> 
<body> 

</body> 
<script> 
var timestamp; 
function callNode() { 

    $.ajax({ 
     url: 'http://xx.xxx.xx.xxx:9000/', 
     dataType: "jsonp", 
     data: {"timestamp":timestamp}, 
     //type: 'POST', //don't need this with jsonp 
     jsonpCallback: "_testcb", 
     cache: false, 
     timeout: 35000, 
     success: function(response, code, xhr) { 
      if ('ok' == response) { 
       console.log(response); 
       callNode(); 
       return false; 
      } 

      console.log(response); 

      timestamp = response.time; 
      // make new call 
      callNode(); 
     }, 
     error: function(jqXHR, textStatus, errorThrown) { 
      console.log('error ' + textStatus + " " + errorThrown); 
     } 
    }); 
} 
$(function() { 
    setTimeout(callNode, 1); //call function with setTimeout in order to avoid ugly constant browser loading 
}); 
</script> 
</html> 

стороны сервера (server.js):

var http = require('http'); 
var mysql = require('mysql'); 
var util = require('util'); 
var url = require('url'); 

var singer_name, currentmodif, lastmodif, request, response, time_of_request; 

//var requests=[]; 

var connection = mysql.createConnection({ 
    host  : 'localhost', 
    user  : 'someone', 
    password : 'xxxxxx', 
    database : 'rest', //mysql database to work with (optional) 
}); 
connection.connect(); //connect to mysql 

connection.query('SELECT * FROM musics WHERE id=1', function(err, rows, fields) { 
    if (err) throw err; 

    singer_name=rows[0].singer_name; 
    currentmodif=rows[0].time_added; 
}); 


http.createServer(function (req, res) { 
    request = req; 
    response = res; 
    time_of_request = new Date().getTime(); 
    console.log('request received'); 


    if(req.method=='GET'){ 
     var url_parts = url.parse(req.url,true); 
     lastmodif = url_parts.query.timestamp; 
    } 

    req.on('error', function(e) { 
     console.log('problem with request: ' + e.message); 
    }); 

    //checkupdate();  

}).listen(9000); 

var response; 

function checkupdate() { 

    var expiration = new Date().getTime() - 30000; 

    //for (var i = requests.length - 1; i >= 0; i--) { 
     //console.log("Request timestamp: "+time_of_request+" Expiration : "+expiration); 
     if (time_of_request < expiration) { 
      console.log("The condition is met"); 
      // return response 
      response.write('_testcb(\'ok\')', 'utf8'); 
      response.end(); 
     } 
    //} 

    connection.query('SELECT * FROM musics WHERE id=1', function(err, rows, fields) { 
     if (err) throw err; 
     currentmodif=rows[0].time_added; 

     if (lastmodif == undefined) 
      lastmodif = 0; 

     console.log("currentmodif: "+currentmodif+" lastmodif: "+lastmodif); 

     if (currentmodif > lastmodif){ 
      singer_name=rows[0].singer_name; 
      var _arrays = {'singer_name': singer_name, 'time': currentmodif} 
      var data = "_testcb"+"("+JSON.stringify(_arrays)+")"; 

      //response.writeHead(200, { 'content-type':'application/json', 
            //'Access-Control-Allow-Origin' : '*'}); 
      //response.write(data); 
      response.end(data); 
      console.log("Response successfully sent"); 
      //return false; 
     } 

    }); 
}; 

setInterval(checkupdate, 2000); 

Проблема был на стороне сервера. Объект ответа не был доступен (он был не определен), когда сервер хотел ответить, и поэтому ответ не отправлялся. Возможно, я упустил ошибку в консоли node.js.

Это почти полный пример длительного опроса с node.js с базой данных MYSQL. Этот скрипт будет ожидать появления новых данных, прежде чем отвечать на запрос ajax. Если свежие данные (в MYSQL) недоступны в течение 30 секунд после запроса, то поддельный ответ делается так, чтобы запрос не тайм-аут. В обратном вызове ajax есть условие, которое повторно инициирует этот запрос ajax, когда этот демонстрационный ответ получен, поэтому делает это бесконечным циклом.

Я успешно протестировал код выше и, похоже, работает нормально. Я запустил скрипт, а затем обновил данные в моей базе данных (в основном поле time_added), и это вызвало ответ на мой ожидающий вызов ajax с новыми данными с сервера node.js.

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

заказ учебник здесь для дальнейшего объяснения: http://www.sahilsaid.com/blog/long-polling-node-js-mysql-database-ajax/

+1

Привет. Дозировать вызов рекурсии функции все время вызовет переполнение стека? –

+0

Я не думаю, что так будет. Мой сервер работает уже более месяца и постоянно не переполняется. Может быть, у node.js есть механизм для решения этой проблемы? – Sahil

+1

Это не вызовет переполнение стека. Это не рекурсия, потому что 'callNode' вызывается обратным вызовом' success' запроса $ .ajax вместо 'callNode', вызывающего себя. Как только запрос 'callNode' выполнит запрос, он выйдет. –

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