使用Node.js流式传输数据

Sai*_*han 42 html ajax jquery node.js data-stream

我想知道是否可以使用Node.js将数据从服务器流式传输到客户端.我想向Node.js发布一个AJAX请求,然后保持连接打开并不断地将数据流传输到客户端.客户端将收到此流并持续更新页面.

更新:

作为这个答案的更新- 我无法让这个工作.在response.write你打电话之前不发送close.我已经设置了一个示例程序,用于实现此目的:

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);
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

使用这种方法,在我打电话之前我什么也得不到close().这是可能的,还是应该采用长轮询方式,而不是在我进入负载功能时再次调用?

Kur*_*aze 26

有可能的.只需多次使用response.write().

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();
Run Code Online (Sandbox Code Playgroud)

您可能必须每30秒左右关闭并重新打开一次连接.

编辑:这是我实际测试的代码:

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');
Run Code Online (Sandbox Code Playgroud)

我通过Telnet连接到它,它确实发出了分块响应.但要在AJAX浏览器中使用它必须支持XHR.readyState = 3(部分响应).据我所知,并非所有浏览器都支持此功能.因此,您最好使用长轮询(或Chrome/Firefox的Websockets).

EDIT2:另外,如果您使用nginx作为Node的反向代理,它有时会想要收集所有块并立即将其发送给用户.你需要调整它.

  • `jquery.load`在触发回调之前等待所有的身体到达.你需要使用不同的东西.见http://api.jquery.com/load/ (3认同)
  • 要使此示例工作:移动"var currentTime = new Date();" 进入setinterval函数. (3认同)

BMi*_*ner 16

看看Sockets.io.它提供HTTP/HTTPS流,并使用各种传输来执行此操作:

  • 的WebSocket
  • WebSocket over Flash(+ XML安全策略支持)
  • XHR轮询
  • XHR Multipart Streaming
  • 永远的iframe
  • JSONP轮询(适用于跨域)

和!它与Node.JS无缝协作.它也是一个NPM包.

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

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


And*_*ukh 5

您还可以中止无限循环:

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);
    }); 
}); 
Run Code Online (Sandbox Code Playgroud)

这是 expressjs 的一个例子。我相信没有 expressjs 会是这样。