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

发布于 2025-01-07 04:02:06 字数 1133 浏览 5 评论 0原文

我有很长的编程背景,但对 Python 很陌生,并且正在使用 Tornado 来制作某个长轮询服务的原型。

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

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

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

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

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

I have long programming background, but am new to Python, and am playing around with Tornado, to prototype a certain long poll service.

What I want to achieve is that user connects to say example.com/get/1234, which is the long poll part. 1234 is the user ID. For now, it just hangs and waits for the content. Then user uses a new tab/other browser/other computer/etc and goes to url like example.com/set/1234?data=abcd, where 1234 is the user ID and data is a variable with content "abcd". Now when this happens, the first get request should print out the data "abcd" and finish the request. User ID is used obviously to allow multiple users to use the service simultaneously. So simply put:

1) Go to example.com/get/1234 -> waiting
2) In another tab, open example.com/set/1234?data=abcd
3) Right after this request, first request prints out abcd and finishes

Below is something I've been trying, but I'm not really advancing with this, nor cannot find proper Google keywords to solve this.

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

All help very much appreciated. Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

§普罗旺斯的薰衣草 2025-01-14 04:02:06

我实际上设法解决了这个问题,找到了解决方案

回顾一下,以防其他人正在研究这一点:我将侦听器保存到带有 user_id 的字典中,当调用 /set 时,我向侦听器发送了消息相同的user_id。如果有人感兴趣,我可以分享更多代码。

I actually managed to fix this, found the solution.

Just to recap in case someone else is looking into this: I saved the listeners to a dict with the user_id and when the /set was called, i messaged the listener with the same user_id. If someone is interested, I can share more code.

扛起拖把扫天下 2025-01-14 04:02:06

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

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。我自己没有使用过这个,但是有一个例子这里< /a>.

A simple workaround is to add a timeout callback

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)

EDIT: A better workaround would be to use websockets + redis + pubsub. I haven't used this myself, but there is an example here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文