2010-02-23 9 views
9

Ich versuche, einfache Web-Anwendung mit Tornado und JS Prototype-Bibliothek zu schreiben. So kann der Client einen langen laufenden Job auf dem Server ausführen. Ich wünschte, dass dieser Job asynchron läuft - damit andere Clients die Seite sehen und dort etwas tun können.Asynchrone COMET-Abfrage mit Tornado und Prototyp

Hier ist, was ich habe:

#!/usr/bin/env/ pytthon 

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

Dieser Server gehört. Es hat Hauptansicht (zeigt wenig Begrüßung, aktuelle Serverzeit und URL für Ajax-Abfrage, die lange laufenden Job ausführt. Wenn Sie eine Taste drücken, wird ein lang laufender Job ausgeführt. Und Server hängt :(Ich kann keine Seiten anzeigen, während .

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

, was mache ich falsch Wie lange Pooling umsetzen können, mit Tornado und Prototype (oder jQuery)

PS:: dieser Job läuft Hier Vorlagenseite ist ich habe im Chat Beispiel sah , aber es ist zu kompliziert.Kann nicht verstehen, wie es funktioniert :(

PSS Herunterladen Voll example

Antwort

15

Tornado ist ein Thread-Webserver. Ihre While-Schleife in wait_for_smith Methode blockiert Tornado.

Sie können diese Methode wie folgt umschreiben:

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

Sie müssen import time an der Spitze hinzuzufügen, diese Arbeit zu machen.

+0

Ich habe diese Methode ausprobiert und kann bestätigen, dass sie nicht mehr hängt, aber jetzt zeigt das Programm eine Warnmeldung an, in der responseText nicht definiert ist und es einen Fehler 405 gibt. – brainysmurf

+0

Sprecht zu schnell, das Problem war auf meinem Ende ... Ich hatte zwei verschiedene Adressen angegeben. Das funktioniert definitiv. – brainysmurf

+0

Aber ist das lang polling? Es sieht so aus, als würde ich nur nachfragen. Wohlgemerkt, ich bin selbst ein Tornado/Comet-Neuling. – Lorenzo

0

Ich habe Tornados Chat-Beispiel konvertiert, um auf gevent zu laufen. Werfen Sie einen Blick auf the live demo here und the explanation and source code here.

Es verwendet leichte User-Level-Threads (greenlets) und ist in Geschwindigkeit/Speicherverbrauch mit Tornado vergleichbar. Der Code ist jedoch einfach, Sie können sleep() und urlopen() in Ihren Handlern aufrufen, ohne den gesamten Prozess zu blockieren, und Sie können Jobs mit langer Laufzeit generieren, die dasselbe tun. Unter der Haube ist die Anwendung asynchron, angetrieben durch eine Ereignisschleife, geschrieben in C (libevent).

Sie können die introduction here lesen.

+0

Nice fork Denis ... – securecurve

1
function test(){ 
      new Ajax.Request("http://172.22.22.22:8888/longPolling", 
      { 
       method:"get", 
       asynchronous:true, 
       onSuccess: function (transport){ 
        alert(transport.responseText); 
       } 
      }) 
     } 

sollte

function test(){ 
      new Ajax.Request("/longPolling", 
      { 
       method:"get", 
       asynchronous:true, 
       onSuccess: function (transport){ 
        alert(transport.responseText); 
       } 
      }) 
     } 
+0

Bei nicht standardmäßigen Ports sollte der gesamte Pfad übergeben werden. – securecurve