手动重新加载网页 Tornado

Posted

技术标签:

【中文标题】手动重新加载网页 Tornado【英文标题】:Manually Reload webPage Tornado 【发布时间】:2015-10-28 14:51:27 【问题描述】:

数据更新时是否可以重新加载页面?

import socket

import tornado.ioloop
import tornado.web
import tornado.gen
import tornado.ioloop
import tornado.iostream
import tornado.tcpserver
import os
import tornado.websocket

last_messages = dict()


class TcpClient(object):

    client_id = 0

    def __init__(self, stream):
        super(TcpClient, self).__init__()
        TcpClient.client_id += 1
        self.id = 'Connection#%d' % TcpClient.client_id
        self.stream = stream

        self.stream.socket.setsockopt(
            socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        self.stream.socket.setsockopt(
            socket.IPPROTO_TCP, socket.SO_KEEPALIVE, 1)
        self.stream.set_close_callback(self.on_disconnect)

    @tornado.gen.coroutine
    def on_disconnect(self):
        self.log("disconnected")
        yield []

    @tornado.gen.coroutine
    def dispatch_client(self):
        try:
            while True:
                line = yield self.stream.read_until(b'\n')

                text_line = line.decode('utf-8').strip()
                last_messages[self.id] = text_line
                # UPDATE GUI, webpage HERE
                self.log('got |%s|' % text_line)
        except tornado.iostream.StreamClosedError:
            pass

    @tornado.gen.coroutine
    def on_connect(self):
        raddr = 'closed'
        try:
            raddr = '%s:%d' % self.stream.socket.getpeername()
        except Exception:
            pass
        self.log('new, %s' % raddr)

        yield self.dispatch_client()

    def log(self, msg, *args, **kwargs):
        print('[%s] %s' % (self.id, msg.format(*args, **kwargs)))


class TcpServer(tornado.tcpserver.TCPServer):
    @tornado.gen.coroutine
    def handle_stream(self, stream, address):
        connection = TcpClient(stream)
        yield connection.on_connect()


class LastMessagesHandler(tornado.web.RequestHandler):

    @tornado.web.asynchronous
    def get(self):
        self.render(
            'template.html',
            sources=last_messages
        )


class WebSocketHandler(tornado.websocket.WebSocketHandler):

    def on_message(self, message):
        print message
        self.write(last_messages)

def main():
    tcp = TcpServer()
    tcp.listen(8008)
    print('tcp://localhost:8008')
    settings = dict(
        template_path=os.path.join(os.path.dirname(__file__), 'templates'),
        static_path=os.path.join(os.path.dirname(__file__), 'static'),
        debug=True,
    )
    app = tornado.web.Application(
        [
            (r'/', LastMessagesHandler),
            (r'/ws', WebSocketHandler)
        ],
        **settings
    )
    app.listen(8009)
    print('http://localhost:8009')

    tornado.ioloop.IOLoop.instance().start()


if __name__ == "__main__":
    main()

这是模板.html

<html>
<head>
<title>TCP server</title>
</head>
<body>
    <title>Tornado WebSockets</title>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script>
        jQuery(function($)
          if (!("WebSocket" in window)) 
            alert("Your browser does not support web sockets");
          else
            setup();
          


          function setup() 
            var host = "ws://localhost:8008/ws";
            var socket = new WebSocket(host);

            // event handlers for websocket
            if(socket)

              socket.onopen = function()
                //alert("connection opened....");
              

              socket.onmessage = function(msg)
                showServerResponse(msg.data);
              

              /*socket.onclose = function()
                //alert("connection closed....");
                showServerResponse("The connection has been closed.");
              */

            else
              console.log("invalid socket");
            

            function showServerResponse(txt)
              var p = document.createElement('p');
              p.innerHTML = txt;
              document.getElementById('output').appendChild(p);
            


          
        );

    </script>
    <div>
        <ul id="output">
        % for key, value in sources.iteritems() %
            <ul> key |  value </ul>
        % end %
        </ul>
    </div>
</body>
</html>

每当 last_messages 更改时,我都需要更新 Client(webpage)(smth 从 dict 中删除,smth 已添加到 dict 中)。我不能使用 tornado.websocket 做到这一点。能否请你帮忙?从套接字读取行后,我需要更新 gui(您可以在我需要更新网页的代码中找到注释:# UPDATE GUI,webpage HERE)。所以套接字仍然可以打开(我们正在继续阅读行),但必须更新 gui。有可能吗?

【问题讨论】:

【参考方案1】:

如果您真的想重新加载页面,那么您可以在 javascript 中发起对 window.location.reload() 的调用。

但是,这会从客户端关闭 WebSocket 连接。

如果你只是想更新 DOM (GUI),那么在客户端监听传入的消息并进行相应的更新。

要观察和跟踪数据更改,您可以使用 JavaScript 自己进行,如果您仅在现代 Chrome 上运行,则可以使用 Object.observe,或者使用 polyfill,或者使用现有工具,例如 Backbone.js。

如果你选择后者,我也可以推荐一个tool to help you with working with WebSockets and Backbone。

免责声明:我是 Backbone.WS 的作者。

【讨论】:

以上是关于手动重新加载网页 Tornado的主要内容,如果未能解决你的问题,请参考以下文章

华为荣耀7i手动更改DNS,提高网页加载速度

Android WebView - 在不重新加载的情况下设置 HTML

为啥手动重用的 UITableViewCell 在重新加载行时会消失?

如何手动重新加载 Passport 快速会话存储

如何在javascript中单击按钮重新加载网页,但在重新加载调用函数后

是啥导致网页重新加载?