44

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

更新:

作为对此答案的更新-我无法使其正常工作。未response.write在您致电之前发送close。我已经设置了一个示例程序,用于实现此目的:

节点.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>

使用这种方法,直到我调用close(). 这是可能的还是我应该采用长轮询方法,而不是在加载函数进来时再次调用它?

4

4 回答 4

28

有可能的。只需多次使用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();

您可能必须每 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');

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

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

于 2010-04-01T20:30:19.423 回答
19

查看 Sockets.io。它提供 HTTP/HTTPS 流,并使用各种传输方式来做到这一点:

  • 网络套接字
  • WebSocket over Flash(+ XML 安全策略支持)
  • XHR 轮询
  • XHR 多部分流式传输
  • 永远的 iframe
  • JSONP 轮询(用于跨域)

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

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

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

于 2011-05-25T20:34:31.907 回答
6

您还可以中止无限循环:

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);
    }); 
}); 

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

于 2012-02-18T21:56:10.993 回答
1

这现在可以通过 Node.jspg-query-stream和 Materialize 实现。

Materialize 与 PostgreSQL 兼容,这意味着 Node.js 应用程序可以使用任何现有的 PostgreSQL 客户端与 Materialize 进行交互。

然而,与 PostgreSQL 不同的是,使用 Materialize,您可以利用 Node.js 应用程序中增量更新的物化视图,而不是在某个时间点查询 Materialize 的视图状态,而是使用TAIL语句来请求更新流作为查看更改。

示例应用程序如下所示:

import express from 'express'
import pg from 'pg'
import QStream from 'pg-query-stream'

const app = express();
const port = 3000

app.get('/questions', async (request, response) => {

    const client = new pg.Client('postgres://materialize@SERVER_IP:6875/materialize');

    await client.connect();

    const query = new QStream('TAIL your_materialized_view WITH (PROGRESS)', [], {batchSize: 1});

    const stream = client.query(query);

    response.setHeader('Content-Type',  'text/event-stream');

    for await (const event of stream) {
        if(event.id){
            response.write(`data: ${JSON.stringify(event)}\n`);
        }
    }

})

app.listen(port)

资源:

于 2021-11-11T19:29:22.167 回答