问题
I want to know if it is possible to stream data from the server to the client with Node.js. I want to post a single AJAX request to Node.js, then leave the connection open and continuously stream data to the client. The client will receive this stream and update the page continuously.
Update:
As an update to this answer - I cannot get this to work. The response.write
is not sent before you call close
. I have set up an example program that I use to achieve this:
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"> </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>
Using this method I don't get anything back until I call close()
. Is this possible or should I go with a long poll approach instead where I call the load function again as one comes in?
回答1:
It is possible. Just use response.write() multiple times.
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();
You may have to close and reopen connection every 30 seconds or so.
EDIT: this is the code I actually tested:
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');
I connected to it by Telnet and its indeed gives out chunked response. But to use it in AJAX browser has to support XHR.readyState = 3 (partial response). Not all browsers support this, as far as I know. So you better use long polling (or Websockets for Chrome/Firefox).
EDIT2: Also, if you use nginx as reverse proxy to Node, it sometimes wants to gather all chunks and send it to user at once. You need to tweak it.
回答2:
Look at Sockets.io. It provides HTTP/HTTPS streaming and uses various transports to do so:
- WebSocket
- WebSocket over Flash (+ XML security policy support)
- XHR Polling
- XHR Multipart Streaming
- Forever Iframe
- JSONP Polling (for cross domain)
And! It works seamlessly with Node.JS. It's also an NPM package.
https://github.com/LearnBoost/Socket.IO
https://github.com/LearnBoost/Socket.IO-node
回答3:
You can also abort the infinite loop:
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);
});
});
This is an example of expressjs. I believe that without expressjs will be something like.
来源:https://stackoverflow.com/questions/2558606/streaming-data-with-node-js