2

我的 Tornado 应用程序中有很多代码,如下所示:

@tornado.web.asynchronous
def get(self):
    ...
    some_async_call(..., callback=self._step1)

def _step1(self, response):
    ...
    some_async_call(..., callback=self._step2)

def _step2(self, response):
    ...
    some_async_call(..., callback=self._finish_request)


def _finish_request(self, response):
    ...
    self.write(something)
    self.finish()

显然,内联回调会大大简化该代码,它看起来像:

@inlineCallbacks
@tornado.web.asynchronous
def get(self):
    ...
    response = yield some_async_call(...)
    ...
    response = yield some_async_call(...)
    ...
    response = yield some_async_call(...)
    ...
    self.write(something)
    self.finish()

有没有办法在 Tornado 中进行内联回调或以其他方式简化代码?

4

3 回答 3

4

你甚至可以分解电话。

我认为您所做的事情是一个接一个地调用异步调用,因此没有提供最大的延迟改进。

如果调用没有任何依赖关系(例如,将一个调用的结果用于第二个调用),您可以同时启动所有调用:

@tornado.web.asynchronous
@gen.engine
def get(self):
    responses = yield [ gen.Task(call) for call in required_calls ]

这样,所有呼叫同时开始,因此您的整体延迟是最大(所有呼叫)而不是总和(所有呼叫)。

我在一个需要聚合许多第三方 WS 或数据库调用的应用程序中使用了它,它大大改善了整体延迟。

当然,如果调用之间存在依赖关系(如上所述),则它不起作用

于 2012-06-27T15:16:41.487 回答
2

找到了。在 Tornado 中,它不被称为内联回调,而是“基于生成器的接口”—— tornado.gen. 因此我的代码应该类似于:

@tornado.web.asynchronous
@gen.engine
def get(self):
    ...
    response = yield gen.Task(some_async_call(...))
    ...
    response = yield gen.Task(some_async_call(...))
    ...
    response = yield gen.Task(some_async_call(...))
    ...
    self.write(something)
    self.finish()
于 2012-06-27T12:54:37.877 回答
2

您也可以考虑只使用Cyclone,这将允许您直接使用@inlineCallbacks(以及您想要的任何其他 Twisted 代码)。

于 2012-06-27T22:45:09.800 回答