em-synchrony将EM事件循环包裹在光纤中。虽然目的是消除嵌套回调块的丑陋,但它增加了一层混乱。我希望进行异步编程,避免在混合使用编程和光纤时出现“无法从根光纤中产生”错误。
我创建了这段代码,我想知道我对它是如何工作的理解是正确的(我试图尽可能简化):
require "eventmachine"
require "em-synchrony"
require "em-synchrony/mysql2"
require "em-synchrony/activerecord"
EM.synchrony do
User.all.each do |user|
Fiber.new {
ImapClient.new(user).check
}.resume
end
end
class ImapClient
attr_accessor :user
def initialize(user)
@user = user
end
def imap_call
client = EM::IMAP.new('imap.gmail.com',993,true)
f = Fiber.current
client.connect.bind! do
client.login(@user.email,@user.password)
end.bind! do
client.select('INBOX')
end.bind! do
client.search(['1:20'])
end.bind! do |ids|
client.fetch(ids, "(UID ENVELOPE BODY[TEXT])")
end.callback do |msgs|
f.resume(msgs)
end.errback do |error|
puts "Connecting or logging in failed: #{error}"
end
return Fiber.yield
end
def check
msgs = imap_call
msgs.each do |msg|
@user.email_messages.create! {body: msg.attr['BODY[TEXT]'], uid: msg.attr['UID']}
end
end
end
1)EM.synchrony将EM的事件循环(代码块)包装在光纤中。
2)我们进行异步数据库查询。据推测,在执行此查询时,synchrony会在后台使用Fiber.yield控制EM事件循环。
3)我们为每个用户记录创建一个新的光纤。 resume调用执行新光纤实例中的代码块。
4)我们执行异步IMAP调用。在等待回调时,我们产生光纤(然后允许我们使用新光纤检查另一个用户的电子邮件)。
5)当调用回调时,恢复旧光纤并检查其消息。
6)然后继续使用较新的光纤,并继续为每个用户记录继续。
这是对的吗?我想确保此代码中没有阻止。