Reputation: 215
In all eventmachine code that I've seen, the callbacks / errorbacks were declared after the actual call of the method.
Here's a simple example:
about = EventMachine::HttpRequest.new('http://google.ca/search?q=eventmachine').get
about.callback { # callback nesting, ad infinitum }
about.errback { # error-handling code }
Why are the callbacks and errorbacks declared AFTER ? Is it not possible that the EM::HttpRequest already finished w/ some sort of success or error state? How does EM guarantee that callbacks and errorbacks are actually caught?
Upvotes: 0
Views: 276
Reputation: 1
Take the following code....
http = EM::HttpRequest.new('http://google.com').get
http.callback {puts "it was a great call"}
http.errback { puts "it was a bad call" }
You might think that if the asynchronous request happens faster than we can set the callback it's possible that the callback will never be called. The request is happening asynchronously so we might think it's a possibility. But it's not. What if we put some really long running code in between the time we actually set up the callback? I'll demostrate and show that the callbacks still work.
http = EM::HttpRequest.new('http://google.com').get
#Some really long running code
100000000000.times do
#some really long running code
end
http.callback {puts "it was a great call"}
http.errback { puts "it was a bad call" }
The request in this case completes long before the really long running code completes but the callback will still be called? Why? The reason is because HttpRequest is a Deferrable. It inherits from it. Even though a Deferrable is something that can run asyc Defferables have a status. success or fail and we still have a reference to that deferable in a variable called http.
When we call http.callback {"puts "it was a great call"} We imediately check to see if the status of the deffereable, in this case http, is success. If it is, imediately call the callback. Else set it up so that the defferable calls it whenever it finishes with a "success" status. It's that simple. As long as we have a reference to that defferable we can set the callback at any time.
My guess was confirmed when I actually took a look at the source code for Defferable. http://eventmachine.rubyforge.org/EventMachine/Deferrable.html#callback-instance_method
Royce
Upvotes: 0
Reputation: 4796
The .get
call only sets up the request.
The get
request method in EM::HttpRequest
module.
EM::HttpRequest
uses EM::Deferrable
module which is sort of a switch.
Add these two together, and you get a functionality where the request is first built and waits until a response is received. So, for the first iteration of the EM.run do..end
loop, the connection is setup, the callbacks are registered and when the response is received, which will be processed in the next iteration/whenever the response is received, the set_deferrable_status
is set to :succeeded
or :failed
and the corresponding callback/errback is executed.
Upvotes: 1