ruby-on-rails – Ruby中的Fibers有什么意义?

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – Ruby中的Fibers有什么意义?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我不明白如下:
  1. counts = Hash.new(0)
  2.  
  3. File.foreach("testfile") do |line|
  4. line.scan(/\w+/) do |word|
  5. word = word.downcase
  6. counts[word] += 1
  7. end
  8. end
  9.  
  10. counts.keys.sort.each {|k| print "#{k}:#{counts[k]} "}

比这更糟糕的是:

  1. words = Fiber.new do
  2. File.foreach("testfile") do |line|
  3. line.scan(/\w+/) do |word|
  4. Fiber.yield word.downcase
  5. end
  6. end
  7. end
  8.  
  9. counts = Hash.new(0)
  10.  
  11. while word = words.resume
  12. counts[word] += 1
  13. end
  14.  
  15. counts.keys.sort.each {|k| print "#{k}:#{counts[k]} "}

解决方法

光纤是一种暂停和恢复任意代码块的方法.像这样的例子并不是一个很好的用例,因为它没有提供任何真正的优势,而不是传统的阅读和处理方式.

在这个特定的例子中,如果你想让它变得更好,你可以编写一个枚举器风格的接口,这样你就可以写:

  1. words = WordsReader.new("testfile")
  2.  
  3. words.each do |word|
  4. # ...
  5. end

纤维变得重要的地方在于编写异步代码.例如,在EventMachine环境中,您需要能够发出异步调用,挂起代码块,并在收到响应时恢复它.

最终看起来像这样:

  1. async_call(argument1,argument2) do |response_1|
  2. if (response_1.ok?)
  3. async_call(argument3,argument4) do |response_2|
  4. if (response_2.ok?)
  5. async_call(argument5,argument6) do |response_3|
  6. if (response_3.ok?)
  7. do_something(response_1,response_2,response_3)
  8. else
  9. panic_and_fail!
  10. end
  11. end
  12. else
  13. panic_and_fail!
  14. end
  15. end
  16. else
  17. panic_and_fail!
  18. end
  19. end

这种嵌套,嵌套和重新嵌套的调用结构被称为“回调地狱”,因为一旦你的逻辑变得非常重要,它就很难管理.平整这种结构的一种方法是使用纤维.适当的纤维化等效物是:

  1. begin
  2. response_1 = fiber_call(argument1,argument2)
  3. response_2 = fiber_call(argument3,argument4)
  4. response_3 = fiber_call(argument5,argument6)
  5.  
  6. do_something(response_1,response_3)
  7.  
  8. rescue NotOkay
  9. panic_and_fail!
  10. end

光纤可以利用异常,其中回调类型代码不能.有效使用时,异常可以大规模简化代码块,如您在此处所见.而不是测试好吗?在每个响应中,预计该调用将抛出NotOkay类型的异常.

回调不能可靠地抛出异常,因为在回调发生时调用的发起者已经超出了范围.这是使用回调进行异步编程的基本限制.光纤驱动的代码维护一个正确的调用堆栈,它只是暂停并按原样恢复,因此异常正确地级联通过调用者.

我发现Fibers既易于理解又很难正确应用.大多数情况下,您不必直接使用它们,您将使用一个使用它们的库.编写“光纤感知”代码与编写“线程安全”代码没有什么不同.做对可能很棘手.

猜你在找的Ruby相关文章