2010-02-23 22 views
9

我正在嘗試使用Tornado和JS Prototype庫編寫簡單的Web應用程序。所以,客戶端可以在服務器上執行長時間運行的作業。我希望,這份工作可以異步運行 - 這樣其他客戶可以查看頁面並在那裏做一些事情。與Tornado和原型的異步COMET查詢

這裏是我已經有了:

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

這是服務器的一部分。它具有主視圖(顯示少量問候語,當前服務器時間和用於執行長時間運行作業的ajax查詢的url)。如果按下按鈕,則會執行長時間運行的作業。服務器掛起:(我無法查看任何頁面,但。這項工作正在運行 這裏是模板頁:

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

我究竟做錯了如何實現長池,採用旋風式和原型(或jQuery的)

PS:我已經看過聊天例子,但它太複雜了。無法理解它是如何工作的:(

PSS下載全部example

回答

15

Tornado是單線程的Web服務器。 wait_for_smith方法中的while循環阻止了Tornado。

可以重寫該方法是這樣的:

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

你需要在頂部加入import time,使這項工作。

+0

我試過這種方法,可以確認它不再掛起,但現在該程序顯示一個警報框,其中responseText未定義,並且存在405錯誤。 – brainysmurf 2010-12-25 08:32:24

+0

說得太快了,問題出在我身上......我指定了兩個不同的地址。這絕對有效。 – brainysmurf 2010-12-25 08:39:05

+0

但是,這是長期投票?它看起來像只是投票給我。請注意,我自己是龍捲風/彗星新手。 – Lorenzo 2011-09-06 23:01:04

0

我已將Tornado的聊天示例轉換爲在gevent上運行。看看the live demo herethe explanation and source code here

它使用輕量級用戶級線程(greenlets),在速度/內存使用方面與Tornado相當。但是,代碼很簡單,您可以在處理程序中調用sleep()和urlopen(),而不會阻塞整個過程,並且可以產生相同的長時間運行的作業。在引擎蓋下,應用程序是異步的,由用C語言編寫的事件循環驅動(libevent)。您可以閱讀introduction here

+0

Nice fork Denis ... – securecurve 2012-12-23 14:16:09

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

應該

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

如果是非默認端口,應該傳遞整個路徑。 – securecurve 2012-12-25 12:29:52