如何在数据可用时完成Tornado长轮询请求

时间:2012-02-17 14:01:01

标签: python asynchronous tornado

我有很长的编程背景,但我是Python的新手,并且正在玩Tornado,为某个长轮询服务做原型。

我想要实现的是用户连接到例如example.com/get/1234,这是漫长的民意调查部分。 1234是用户ID。现在,它只是挂起并等待内容。然后用户使用新的选项卡/其他浏览器/其他计算机/等,并转到url,如example.com/set/1234?data=abcd,其中1234是用户ID,数据是内容为“abcd”的变量。现在发生这种情况时,第一个get请求应打印出数据“abcd”并完成请求。显然,用户ID允许多个用户同时使用该服务。所以简单地说:

1)转到example.com/get/1234 - >等候 2)在另一个选项卡中,打开example.com/set/1234?data=abcd 3)在此请求之后,第一个请求打印出abcd并完成

以下是我一直在努力的事情,但我并没有真正推进这一点,也找不到合适的Google关键字来解决这个问题。

class GetHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous

    # Getting user ID is working
    def get(self, user_id):

        # This is something I'm not sure is right, but found it in an 
        # example. I haven't created the code_received function yet, 
        # nor know if it should be here? Should the code_received
        # and connection finishing be called from the /set part?

        cursor = self.get_argument("cursor", None)
        self.wait_for_code(self.code_received, cursor=cursor)

    def code_received(self, data)
        self.write(data)
        self.finish()

非常感谢所有人的帮助。提前谢谢!

2 个答案:

答案 0 :(得分:1)

一个简单的解决方法是添加超时回调

class GetHandler(tornado.web.RequestHandler):

    @tornado.web.asynchronous
    def get(self, user_id):    

        def check():
            # here you must implement something to discover if the result exists
            # for example, you can keep a dictionary with id : result 
            # so initially 1234 : None
            # after setting 1234 : someVal (this happens from the SetHandler)
            # then if below succeeds
            if there_is_a_result:
                self.write(result) 
                self.finish()
            else:   # result not ready, add another timeout callback
                tornado.ioloop.IOLoop.instance().add_timeout(datetime.timedelta(0.00001), check)

        tornado.ioloop.IOLoop.instance().add_timeout(datetime.timedelta(0.00001), check)

编辑:更好的解决方法是使用websockets + redis + pubsub。我自己没有使用过,但有一个例子here

答案 1 :(得分:1)

我确实设法解决了这个问题,找到了solution

只是为了回顾一下其他人正在研究这个:我用user_id将听众保存到一个字典中,当/set被调用时,我向听众传达了相同的{{1} }}。如果有人感兴趣,我可以分享更多代码。