Ruby 可延迟与回调接口
使用可延迟而不是回调的好处是什么。小例子Ruby 可延迟与回调接口,ruby,asynchronous,eventmachine,Ruby,Asynchronous,Eventmachine,使用可延迟而不是回调的好处是什么。小例子 # This is Deferrable interface request = NetworkIO.get request.callback do |resp| puts "Job is done" end request.errback do |err| puts "Oh. My name is Forest, Forest Gump" end # And this is callback interface NetworkIO.get d
# This is Deferrable interface
request = NetworkIO.get
request.callback do |resp|
puts "Job is done"
end
request.errback do |err|
puts "Oh. My name is Forest, Forest Gump"
end
# And this is callback interface
NetworkIO.get do |resp|
if Exception === resp
puts "Oh. My name is Forest, Forest Gump"
else
puts "Job is done!"
end
end
# Or node js style
NetworkIO.get do |err, resp|
if err
puts "Oh. My name is Forest, Forest Gump"
else
puts "Job is done!"
end
end
Deferrable有两个嵌套级别,而回调有三个嵌套级别
正如我所看到的,例如,使用可延迟对象,您可以传递errback,并只定义callback。这在某些情况下是有意义的,因此代码变得更可读,代码行更少,嵌套更少
但是。我发现了一个恼人的案子。例如,您得到了这个伪异步API
class SomeIO
def find(msg)
response = DeferrableResponse.new
req = socket.send(msg)
req.callback do |data|
response.succeed(data)
end
req.errback do |err|
response.fail(err)
end
response
end
def count(msg)
response = DeferrableResponse.new
req = find(msg)
req.callback do |data|
response.succeed(data.size)
end
req.errback do |err|
response.fail(err)
end
response
end
end
它在回调模式下应该是什么样子
class SomeIO
def find(msg, &blk)
socket.send(msg) do |resp|
blk.call(resp)
end
end
def count(msg, &blk)
find(msg) do |resp|
if Exception === resp
blk.call(resp)
else
cnt = resp.size
blk.call(cnt)
end
end
end
end
就我的口味而言,即使现在它看起来也有点干净。但它是主观的。想象一下,您将支持SynchronouseAPI而不是异步API。使用可延迟接口,您应该将所有具有可延迟响应的方法包装到光纤中(这是一项非常大的工作,需要非常繁重的支持),而在回调中,您必须仅在trully async ops上调用光纤:
class SyncSomeIO < SomeIO
def find(msg, &blk)
fib = Fiber.current
socket.send(msg) do |resp|
fib.resume(resp)
end
res = Fiber.yield
raise res if res === Exception
res
end
end
这是一个很小的改变,但只需几行代码,您的API就可以在同步和异步模式下工作
抱歉这么大的介绍,谢谢你们的阅读(你们两个)
问题是。Deferrable实际上是Ruby中事件api的标准。也许我误解了什么,我用了错误的方法?也许回调接口有异味,并且出现了一些不好的问题
PS:我写这一切是因为我正在EventMachine上开发MongoDB驱动程序,现在正在向客户端添加synchronouse接口。并最终意识到,由于延迟,我应该对所有公共API进行修补,以添加同步支持,并考虑在回调时重写它。如果您控制
延迟的接口,您可以按照以下方式执行操作:
class DeferrableResponse
def sync
fiber = Fiber.current
callback { |val| fiber.resume(val) }
errback { |err| fiber.resume(err) }
result = Fiber.yield
raise result if result.is_a? Exception
result
end
end
这将允许您像这样使用同步API:
response = NeworkIO.get.sync
但是你可以用回调接口做同样的事情:)也许我不理解你的问题。你能不能换一种说法,问一些更简洁、更具体的问题?我的问题相当笼统:如果延迟使API更复杂,更难在其上支持同步接口,为什么我需要使用延迟呢。
response = NeworkIO.get.sync