Reputation: 1232
I have a simple handler like so :
@asynchronous
@gen.engine
def post(self):
result = functionOne()
foo = MyObject()
bar = AnotherObject()
But I'd like for result to come back, then execute foo, then bar in a sequence. I've tried using nested callbacks as per http://www.tornadoweb.org/documentation/gen.html but without much luck.
thx!
Upvotes: 1
Views: 1991
Reputation: 3985
You are using the gen.engine, but you need to make your method calls into yield
with a gen.Task
calls.
Example from a project of mine:
customer = yield gen.Task( self.paymentService.charge, email, cardUri )
sub = yield gen.Task( self.paymentService.schedule, customer )
The above will first do the charge
part then return the result and then call the schedule
and return the subscription
object from that call.
The methods that you call with the gen.Task
need to look like the following:
def customer( self, email, cardUri, callback=None ):
Where callback
will be the function to call to actually return the value from the gen.Task
.
I have it setup to work with or without the callback so I can more easily test my methods. Which is just a simple test if callback
is None
or not and if it isn't None
then it gets called else it returns normally.
EDIT:
Ok, to clarify the above it a complete function that works with gen.Tasks
looks like the following.
def delete_customer( customer_id, callback ):
result = customerService.delete( customer_id )
callback( result )
The above when used in a gen.Task
will look like the following.
@gen.engine
def perform_customer_delete( customer_id )
result = yield gen.Task( delete_customer, customer_id )
return result
This means to call the delete_customer
with the parameter customer_id
and then I want the result of this function, the return, to be given to result
. So, when the delete_customer
function completes and sends the result
of the self.customerService.delete
to the callback
the gen.Task
will then return the value and store it in result
.
Now, you can use the result
however you wish, in my example it is returned.
For you example it looks like you want to do the following.
@asynchronous
@gen.engine
def post(self):
result = yield gen.Task( functionOne )
foo = yield gen.Task( MyObject )
bar = yield gen.Task( AnotherObject )
This will first call the functionOne
then go to the next gen.Task
and execute the MyObject
and so forth. But, you must follow the pattern where you have a callback
parameter in your methods in order to use gen.Task
correctly otherwise you cannot get the result back.
This is where my second, confusing example, comes into play.
In order to get around this requirement and to allow my code to work with gen.Task
and without I do the following.
def delete_customer( customer_id, callback=None ):
result = customerService.delete_customer( customer_id )
if callback:
callback( result )
return result
This allows me to use the code in a lot more situations without breakage.
Upvotes: 4