我知道光纤是合作线程。光纤控制执行上下文,而抢先线程则不控制。光纤可以控制光纤,这意味着光纤可以在明确定义的位置开始和停止。
显然,纤维用于红宝石的原因是为了清理由反应器模式引起的嵌套块。
但是我很难掌握下面使用光纤的脚本的控制流程。
def http_get(url)
f = Fiber.current
http = EventMachine::HttpRequest.new(url).get
# resume fiber once http call is done
http.callback { f.resume(http) }
http.errback { f.resume(http) }
return Fiber.yield
end
EventMachine.run do
Fiber.new{
page = http_get('http://www.google.com/')
puts "Fetched page: #{page.response_header.status}"
if page
page = http_get('http://www.google.com/search?q=eventmachine')
puts "Fetched page 2: #{page.response_header.status}"
end
}.resume
end
我理解它的方式:
1)EM启动其事件循环
2)创建光纤然后调用简历。传递给new的代码块是否立即执行或者在调用resume之后执行它?
3)第一次调用http_get。它执行异步事件(在linux上使用select,poll或epoll)。我们设置了异步事件的事件处理程序(在回调方法中)。然后Fiber自动控制线程EventMachine打开(主线程)。但是,一旦调用回调,它将使用f.resume(http)进行控制。但是在这个简化的例子中,我应该在f.resume(http)之后放置我自己的回调代码吗?因为现在似乎f.resume(http)只是将控制返回到光纤而没有做任何事情。
我认为在yield之后发生的事情是控件进入EventMachine进入其事件循环。所以第二个http_get还没有被调用。现在一旦调用回调,然后控制返回到光纤(我们只使用一个Fiber.new,所以我假设所有这些中只有一个光纤实例)。但第二个http_get什么时候被调用?
答案 0 :(得分:1)
让我看看能不能为你解答。我正在添加行号以帮助描述:
01: def http_get(url)
02: f = Fiber.current
03: http = EventMachine::HttpRequest.new(url).get
04:
05: # resume fiber once http call is done
06: http.callback { f.resume(http) }
07: http.errback { f.resume(http) }
08:
09: return Fiber.yield
10: end
11:
12: EventMachine.run do
13: Fiber.new{
14: page = http_get('http://www.google.com/')
15: puts "Fetched page: #{page.response_header.status}"
16:
17: if page
18: page = http_get('http://www.google.com/search?q=eventmachine')
19: puts "Fetched page 2: #{page.response_header.status}"
20: end
21: }.resume
22: end
google.come
上执行GET。在第17行,它检查来自http_get
的响应是否有效,然后在第18行执行下一个请求以搜索字符串eventmachine
。.resume
而开始时,执行第14行,调用http_get
方法。http
对象的引用,该对象现在在第14行中用变量page
引用,随后在第15行中使用转储HTTP请求状态。page
是否为真值,然后继续并再次调用http_get
,但使用新的URL。请注意,代码if page
可能永远不会执行,因为它是nil
,因为第15行会在没有page
检查的情况下被nil
访问的位置进行轰炸。希望澄清此事。
至于使用附加逻辑处理HTTP GET的响应,我猜你可以用一些有意义的处理逻辑替换puts
。此示例中的puts
似乎处理响应,回调主要用于恢复光纤。