Kirill
Kirill

Reputation: 33

Manually Reload webPage Tornado

Is it possible to make reload the page when the data is updated?

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()

Here is the template.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>

I need to update Client(webpage) whenever last_messages is changed (smth is removed form the dict, smth has been added to the dict). I can't do this using tornado.websocket. Could you please help? I need to update gui after reading line from the socket (you can find the comment in the code where i need to update the webpage: # UPDATE GUI, webpage HERE). So the socket can be still opened (we are continuing reading lines), but the gui must be updated. Is it possible to do it?

Upvotes: 0

Views: 833

Answers (1)

ydaniv
ydaniv

Reputation: 1289

If you really want to reload the page then in your JavaScript you can initiate a call to window.location.reload().

However, this will close the WebSocket connection from the client side.

If you just wish to update the DOM (GUI), then listen to the incoming message on the client and update accordingly.

To observe and track data changes you can do it yourself in JavaScript, or with Object.observe if you're running only on modern Chrome, or with the polyfill, or use an existing tool, like Backbone.js.

Should you choose the latter, I can also recommend a tool to help you with working with WebSockets and Backbone.

Disclaimer: I'm the author of Backbone.WS.

Upvotes: 1

Related Questions