Skip to content

Instantly share code, notes, and snippets.

@stuxcrystal
Created June 7, 2019 15:30
Show Gist options
  • Save stuxcrystal/d5685dd217fa53c207ab097f225da28c to your computer and use it in GitHub Desktop.
Save stuxcrystal/d5685dd217fa53c207ab097f225da28c to your computer and use it in GitHub Desktop.
Async-Await with Ruby/EventMachines
class Async
Value = Struct.new(:error, :value)
module ClassMethods
def async(funcname)
async = ::Async.new(&method(funcname))
define_method :funcname do |*args, &block|
async.call(*args, &block)
end
end
end
Module.extend ClassMethods
module InstanceMethods
def await(future)
result = Fiber.current.yield future
return if result.nil?
return result.value if result.error.nil?
raise result.error
end
end
Object.extend InstanceMethods
def initialize(&block)
@block = block
end
def _continue_one(deferred, fiber, result)
begin
future = fiber.resume(result)
ensure => error
deferred.fail(error)
return
end
if fiber.dead?
deferred.succeed(future)
return
end
future.errback do |error|
_continue_one(deferred, fiber, Value.new(error, nil))
end
future.callback do |value=nil|
_continue_one(deferred, fiber, Value.new(nil, value))
end
end
def _start(fiber)
deferrable = EventMachine::Deferrable.new
_continue_one(deferrable, fiber, nil)
return deferrable
end
def call(*args, &block)
_start Fiber.new do
@block.call(*args, &block)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment