据我所知,来自tornado.gen模块的文件是tornado.gen.Task包含tornado.gen.Callback和tornado.gen.Wait,每个Callback / Wait对与唯一键相关联......
@tornado.web.asynchronous
@tornado.gen.engine
def get(self):
http_client = AsyncHTTPClient()
http_client.fetch("http://google.com",
callback=(yield tornado.gen.Callback("google")))
http_client.fetch("http://python.org",
callback=(yield tornado.gen.Callback("python")))
http_client.fetch("http://tornadoweb.org",
callback=(yield tornado.gen.Callback("tornado")))
response = yield [tornado.gen.Wait("google"), tornado.gen.Wait("tornado"), tornado.gen.Wait("python")]
do_something_with_response(response)
self.render("template.html")
因此,上面的代码将获取来自不同URL的所有响应。 现在我真正需要完成的是一旦http_client返回数据就返回响应。因此,如果'tornadoweb.org'首先返回数据,它应该执行self.write(respose),并且def get()中的循环应该等待其他http_clients完成。 关于如何使用tornado.gen接口编写此内容的任何想法。
我想要做的非常模糊的实现(以及语法错误)将是这样的
class GenAsyncHandler2(tornado.web.RequestHandler):
@tornado.web.asynchronous
@tornado.gen.engine
def get(self):
http_client = AsyncHTTPClient()
http_client.fetch("http://google.com",
callback=(yield tornado.gen.Callback("google")))
http_client.fetch("http://python.org",
callback=(yield tornado.gen.Callback("python")))
http_client.fetch("http://tornadoweb.org",
callback=(yield tornado.gen.Callback("tornado")))
while True:
response = self.get_response()
if response:
self.write(response)
self.flush()
else:
break
self.finish()
def get_response(self):
for key in tornado.gen.availableKeys():
if key.is_ready:
value = tornado.gen.pop(key)
return value
return None
答案 0 :(得分:4)
这种情况是,您不应该使用inline callbacks
,即gen
。
在所有回调完成后,也将调用self.render
。 如果您想部分从服务器返回响应 - 部分呈现它。
以这种方式思考(这是唯一有改进空间的想法):
response = []
@tornado.web.asynchronous
def get(self):
self.render('head.html')
http_client = AsyncHTTPClient()
http_client.fetch("http://google.com",
callback=self.mywrite)
http_client.fetch("http://python.org",
callback=self.mywrite)
http_client.fetch("http://tornadoweb.org",
callback=self.mywrite)
self.render('footer.html')
self.finish()
def mywrite(self, result):
self.render('body_part.html')
self.response.add(result)
if len(self.response) == 3:
do_something_with_response(self.response)
答案 1 :(得分:3)
除此之外,实际上有一个方法WaitAll等待所有结果,并在所有HTTPCliens完成给出响应时返回。 我在龙卷风分支(https://github.com/pranjal5215/tornado)中提交了差异。我添加了一个WaitAny类,它是异步WaitAll,并在一个HTTPClient返回结果后立即返回结果。
差异在(https://github.com/pranjal5215/tornado/commit/dd6902147ab2c5cbf2b9c7ee9a35b4f89b40790e),(https://github.com/pranjal5215/tornado/wiki/Add-WaitAny-to-make-WaitAll-return-results-incrementally)
样本用法:
class GenAsyncHandler2(tornado.web.RequestHandler):
@tornado.web.asynchronous
@tornado.gen.engine
def get(self):
http_client = AsyncHTTPClient()
http_client.fetch("http://google.com",
callback=(yield tornado.gen.Callback("google")))
http_client.fetch("http://python.org",
callback=(yield tornado.gen.Callback("python")))
http_client.fetch("http://tornadoweb.org",
callback=(yield tornado.gen.Callback("tornado")))
keys = set(["google", "tornado", "python"])
while keys:
key, response = yield tornado.gen.WaitAny(keys)
keys.remove(key)
# do something with response
self.write(str(key)+" ")
self.flush()
self.finish()