I've faced an ambiguous situation with asynchronous functions in Tornado.
The system I've been working on receives only POST requests and serves them asynchroniously. But now i must add GET request handling for serving IE8 users. The problem is that GET request functionality is exactly the same as in post request.
I don't want co simply copy-paste my code, so i've came to the following solution:
class ExampleHandler(BaseHandler):
def _request_action(self):
""" Function that incapsulates all actions, that should be performed in request
"""
yield self.motor.col1.insert({"ex1": 1})
raise Return
@gen.coroutine
def get(self):
""" GET request handler - need for IE8- users. Used ONLY for them
"""
self._request_action()
@gen.coroutine
def post(self):
""" POST handling for all users, except IE8-
"""
self._request_action()
I have a lot of doubts about async decorators. Is it enough to wrap GET/POST handlers in decorators, and put all actions that should be performed in a synchronously working function? Or i should wrap it too?
If you yield
a Future
inside a function, you have to wrap it with @gen.coroutine
.
So, wrap _request_action
with @gen.coroutine
@gen.coroutine
def _request_action(self):
""" Function that incapsulates all actions, that should be performed in request
"""
result = yield self.motor.col1.insert({"ex1": 1})
raise gen.Return(result) # that is how you can return result from coroutine
And also, all coroutines must be called by yield
:
@gen.coroutine
def get(self):
""" GET request handler - need for IE8- users. Used ONLY for them
"""
result = yield self._request_action()
# do something with result, if you need
@gen.coroutine
def post(self):
""" POST handling for all users, except IE8-
"""
result = yield self._request_action()
# do something with result, if you need