2010-02-23 16 views
9

Próbuję napisać prostą aplikację internetową przy użyciu biblioteki Tornado i JS Prototype. Klient może więc wykonywać długo działające zadanie na serwerze. Chciałbym, aby ta praca była uruchamiana asynchronicznie - aby inni klienci mogli wyświetlać stronę i robić tam pewne rzeczy.Asynchroniczne zapytanie COMET z Tornadem i prototypem

Oto co mam:

#!/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() 

Jest to część serwera. Ma widok główny (pokazuje małe powitanie, aktualny czas serwera i URL dla zapytania ajax, który wykonuje długo działające zadanie, jeśli naciśniesz przycisk, długo działa zadanie, a serwer się zawiesza :(nie widzę żadnych stron, . ta praca jest uruchomiony Oto szablon strony:

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

co robię źle Jak można realizować długie buforowanie, używając Tornado i Prototype (lub jQuery)

PS: mam spojrzał na Chat przykład , ale to zbyt skomplikowane.Nie mogę zrozumieć, jak to działa :(

PSS Pobierz pełny example

Odpowiedz

15

Tornado jest jednowątkowym serwerem WWW. Twoja pętla while w metodzie wait_for_smith blokuje Tornado.

Możesz przerobić tę metodę tak:

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

Trzeba dodać import time na górze, aby uczynić tę pracę.

+0

Próbowałem tej metody na zewnątrz i może potwierdzić, że to już nie zawiesza się, ale teraz program wyświetla się okno alertu gdzie responseText nie jest określony i nie ma błędu 405. – brainysmurf

+0

Mówił zbyt szybko, problem był na moim końcu ... Miałem dwa różne adresy określone. To na pewno działa. – brainysmurf

+0

Ale czy to jest długi głos? Wygląda mi na to, że właśnie wyszukałem. Pamiętaj, że sam jestem początkującym Tornadem/Kometą. – Lorenzo

0

Przekonwertowałem przykład czatu Tornado do uruchomienia na gevent. Spójrz na the live demo here i the explanation and source code here.

Wykorzystuje lekkie wątki na poziomie użytkownika (greenlets) i jest porównywalne pod względem prędkości/pamięci w Tornado. Jednak kod jest prosta, można wywołać sen() i urlopen() w teleskopowe bez blokowania całego procesu i można tarło długo uruchomionych zadań, które robią to samo. Pod maską aplikacja jest asynchroniczna, zasilana przez pętlę zdarzeń napisaną w C (libevent).

Możesz przeczytać introduction here.

+0

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

powinny być

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

w przypadku portów innych niż domyślne, cała ścieżka powinna być przekazywane. – securecurve