Как сказал @maniacalrobot, используя EM.defer/deferrable
, можно пропустить прок, не блокируя реактор. Но тогда вы вводите «callback hell», когда вам нужно последовательно запускать несколько procs.
Я знаю два решения, чтобы сделать код более читаемым: обещания и волокна.
Обещание дает хороший API сочинить асинхронные вызовы, есть много хороших статьи там, в том числе:
волокон являются более рубиновый специфический инструмент, который заставляет ваш код выглядеть синхронно, делая асинхронные вещи.
Вот вспомогательный метод для выполнения процедурного асинхронно (отложенный), но по-прежнему блокировать код вызова без блокировки основного реактора (это магия Fibers):
def deferring(action)
f = Fiber.current
safe_action = proc do
begin
res = action.call
[nil, res]
rescue => e
[e, nil]
end
end
EM::defer(safe_action, proc { |error, result| f.resume([error, result]) })
error, result = Fiber.yield
raise error if error
result
end
Пример использования:
action1_res = deferring(proc do
puts 'Async action 1'
42
end
begin
deferring(proc do
puts "Action1 answered #{action1_res}"
raise 'action2 failed'
end)
rescue => error
puts error
end
Итак, для более простого примера я могу просто назвать 'deferring (proc1); отложив (proc2); deffering (proc3) '?? – Ovesh
Кроме того, технически, отложенная процедура может завершиться до вызова 'Fiber.yield'. что происходит, когда вы вызываете 'resume' на волокно, которое не заблокировано? (Я понимаю, что это может быть крайний вопрос noob) – Ovesh
@ Овеш, да к первому вопросу, это простейший случай, без возвращаемого значения или обработки ошибок. – patatepartie