web-dev-qa-db-fra.com

Streaming de données avec Node.js

Je veux savoir s'il est possible de diffuser des données du serveur vers le client avec Node.js. Je souhaite publier une seule requête AJAX à Node.js, puis laisser la connexion ouverte et diffuser en continu les données au client. Le client recevra ce flux et mettra à jour la page en continu.

Mettre à jour:

En tant que mise à jour de cette réponse - Je ne peux pas faire fonctionner cela. Le response.write N'est pas envoyé avant d'appeler close. J'ai mis en place un exemple de programme que j'utilise pour y parvenir:

Node.js:

var sys = require('sys'), 
http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    var currentTime = new Date();
    setInterval(function(){
        res.write(
            currentTime.getHours()
            + ':' + 
            currentTime.getMinutes()
            + ':' +
            currentTime.getSeconds()
        );
    },1000);
}).listen(8000);

HTML:

<html>
    <head>
        <title>Testnode</title>
    </head>

    <body>
        <!-- This fields needs to be updated -->
        Server time: <span id="time">&nbsp;</span>

        <!-- import jQuery from google -->
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

        <!-- import jQuery -->
        <script type="text/javascript">
            $(document).ready(function(){
            // I call here node.localhost nginx ports this to port 8000
                $('#time').load('http://node.localhost');
            });
        </script>
    </body>
</html>

En utilisant cette méthode, je ne récupère rien tant que je n'appelle pas close(). Est-ce possible ou devrais-je adopter une approche d'interrogation longue à la place où j'appelle à nouveau la fonction de chargement lorsque l'on entre?

42
Saif Bechan

C'est possible. Utilisez simplement response.write () plusieurs fois.

var body = ["hello world", "early morning", "richard stallman", "chunky bacon"];
// send headers
response.writeHead(200, {
  "Content-Type": "text/plain"
});

// send data in chunks
for (piece in body) {
    response.write(body[piece], "ascii");
}

// close connection
response.end();

Vous devrez peut-être fermer et rouvrir la connexion toutes les 30 secondes environ.

[~ # ~] modifier [~ # ~] : voici le code que j'ai testé:

var sys = require('sys'),
http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    var currentTime = new Date();
    sys.puts('Starting sending time');
    setInterval(function(){
        res.write(
            currentTime.getHours()
            + ':' +
            currentTime.getMinutes()
            + ':' +
            currentTime.getSeconds() + "\n"
        );

        setTimeout(function() {
            res.end();
        }, 10000);

    },1000);
}).listen(8090, '192.168.175.128');

Je me suis connecté à Telnet et sa réponse donne en effet des morceaux. Mais pour l'utiliser dans AJAX doit prendre en charge XHR.readyState = 3 (réponse partielle). Tous les navigateurs ne le prennent pas en charge, pour autant que je sache. Il vaut donc mieux utiliser l'interrogation longue (ou les Websockets pour Chrome/Firefox).

EDIT2 : De plus, si vous utilisez nginx comme proxy inverse pour Node, il souhaite parfois rassembler tous les morceaux et l'envoyer à l'utilisateur en même temps. Vous devez le modifier.

26
Kuroki Kaze

Regardez Sockets.io. Il fournit un streaming HTTP/HTTPS et utilise divers transports pour ce faire:

  • WebSocket
  • WebSocket sur Flash (+ prise en charge de la politique de sécurité XML)
  • Interrogation XHR
  • Streaming multipartie XHR
  • Iframe pour toujours
  • Interrogation JSONP (pour le domaine croisé)

Et! Il fonctionne parfaitement avec Node.JS. C'est aussi un package NPM.

https://github.com/LearnBoost/Socket.IO

https://github.com/LearnBoost/Socket.IO-node

16
BMiner

Vous pouvez également abandonner la boucle infinie:

app.get('/sse/events', function(req, res) {
    res.header('Content-Type', 'text/event-stream');

    var interval_id = setInterval(function() {
        res.write("some data");
    }, 50);

    req.socket.on('close', function() {
        clearInterval(interval_id);
    }); 
}); 

Ceci est un exemple d'expressjs. Je crois que sans expressjs sera quelque chose comme.

4
Andrey Antukh