Asynchronous COMET query with Tornado and Prototype

ajax, comet, long-polling, python, tornado

Solution

Tornado is single-threaded web server. Your while loop in `wait_for_smith` method is blocking Tornado.

You can rewrite that method like this:

def wait_for_smth(self, callback, t=10):
    if t:
        print "Sleeping 2 second, t=%s" % t
        tornado.ioloop.IOLoop.instance().add_timeout(time.time() + 2, lambda: self.wait_for_smth(callback, t-1))
    else:
        callback()

You need to add `import time` at the top to make this work.

Problem

I'm trying to write simple web application using Tornado and JS Prototype library. So, the client can execute long running job on server. I wish, that this job runs Asynchronously - so that others clients could view page and do some stuff there. Here's what I've got: ``` #!/usr/bin/env/ python import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web from tornado.options import define, options import os import string from time import sleep from datetime import datetime define("port", default=8888, help="run on the given port", type=int) class MainHandler(tornado.web.RequestHandler): def get(self): self.render("templates/index.html", title="::Log watcher::", c_time=datetime.now()) class LongHandler(tornado.web.RequestHandler): @tornado.web.asynchronous def get(self): self.wait_for_smth(callback=self.async_callback(self.on_finish)) print("Exiting from async.") return def wait_for_smth(self, callback): t=0 while (t < 10): print "Sleeping 2 second, t={0}".format(t) sleep(2) t += 1 callback() def on_finish(self): print ("inside finish") self.write("Long running job complete") self.finish() def main(): tornado.options.parse_command_line() settings = { "static_path": os.path.join(os.path.dirname(__file__), "static"), } application = tornado.web.Application([ (r"/", MainHandler), (r"/longPolling", LongHandler) ], **settings ) http_server = tornado.httpserver.HTTPServer(application) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start() if __name__ == "__main__": main() ``` This is server part. It has main view (shows little greeting, current server time and url for ajax query, that executes long running job. If you press a button, a long running job executes. And server hangs :( I can't view no pages, while this job is running. Here is template page: ``` <html> <head> <title>{{ title }}</title> <script type="text/javascript" language="JavaScript" src="{{ static_url("js/prototype.js")}}"></script> <script type='text/javascript' language='JavaScript'> offset=0 last_read=0 function test(){ new Ajax.Request("http://172.22.22.22:8888/longPolling", { method:"get", asynchronous:true, onSuccess: function (transport){ alert(transport.responseText); } }) } </script> </head> <body> Current time is {{c_time}} <br> <input type="button" value="Test" onclick="test();"/> </body> </html> ``` what am I doing wrong? How can implement long pooling, using Tornado and Prototype (or jQuery) PS: I have looked at Chat example, but it too complicated. Can't understand how it works :( PSS Download full example

Original source