Ruby Async Gem:基本使用示例是什么?

Chr*_*bek 7 ruby asynchronous fibers

使用 Ruby 3.0,asyncgem现在与标准库函数中的阻塞 IO 兼容,我想了解基本功能,但已经被一个简单的示例困惑了:

require 'async'

n = 10
n.times do |i|
  Async do
    HTTParty.get("https://httpbin.org/delay/1.6")
  end
end
Run Code Online (Sandbox Code Playgroud)

这没有表现出任何并行性。查看 Gem 的文档,内容Kernel#async如下:

异步运行任务中给定的代码块,并在必要时创建反应器。

项目文档似乎澄清了这一点:

在顶层调用时,将创建并运行反应器,并将块作为异步任务调用。将阻塞直到反应堆完成运行。

因此,要使上面的示例起作用:

require 'async'

n = 10
Async do
  n.times do |i|
    Async do
      HTTParty.get("https://httpbin.org/delay/1.6")
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

这可行,但对读者来说似乎很混乱。作为读者,我们如何知道第一个Async do被阻塞而其他则没有?

因此问题是:宝石的规范基本用法是什么async

进一步阅读:

pix*_*aki 0

如果您的问题是“gem 的基本示例是什么async”,那么您的第二个代码片段就是其中之一。

如果您的问题是“为什么 API 是这样的?”,那么您可能需要询问在其问题板上开发该 gem 的开发人员。

如果您的问题是“如何判断运行Async::Reactor(确实如此Kernel#Async)是否会阻塞,您可以调用Async#Task.current?

require 'async'
require 'net/http'

def log_whether_blocking
  if Async::Task.current?
    puts "Async::Task#current? is truthy, calling `Kernel#Async` will not block"
  else
    puts "Async::Task#current? is falsey, calling `Kernel#Async` will block"
  end
end

n = 10
Async do
  n.times do |i|
    log_whether_blocking
    Async do
      Net::HTTP.get(URI("https://httpbin.org/delay/1.6"))
    end
  end
end

n.times do |i|
  log_whether_blocking
  Async do
    Net::HTTP.get(URI("https://httpbin.org/delay/1.6"))
  end
end
Run Code Online (Sandbox Code Playgroud)

这给出了输出

Async::Task#current? is truthy, calling `Kernel#Async` will not block
Async::Task#current? is truthy, calling `Kernel#Async` will not block
Async::Task#current? is truthy, calling `Kernel#Async` will not block
Async::Task#current? is truthy, calling `Kernel#Async` will not block
Async::Task#current? is truthy, calling `Kernel#Async` will not block
Async::Task#current? is truthy, calling `Kernel#Async` will not block
Async::Task#current? is truthy, calling `Kernel#Async` will not block
Async::Task#current? is truthy, calling `Kernel#Async` will not block
Async::Task#current? is truthy, calling `Kernel#Async` will not block
Async::Task#current? is truthy, calling `Kernel#Async` will not block
Async::Task#current? is falsey, calling `Kernel#Async` will block
Async::Task#current? is falsey, calling `Kernel#Async` will block
Async::Task#current? is falsey, calling `Kernel#Async` will block
Async::Task#current? is falsey, calling `Kernel#Async` will block
Async::Task#current? is falsey, calling `Kernel#Async` will block
Async::Task#current? is falsey, calling `Kernel#Async` will block
Async::Task#current? is falsey, calling `Kernel#Async` will block
Async::Task#current? is falsey, calling `Kernel#Async` will block
Async::Task#current? is falsey, calling `Kernel#Async` will block
Async::Task#current? is falsey, calling `Kernel#Async` will block
Run Code Online (Sandbox Code Playgroud)

虽然对于那些不熟悉 API 的人来说,这可能是一个潜在的枪械,但Async::Reactor如果将其包装在调用中,您始终可以确保同时运行一组 s Kernel#Async,尽管在某些情况下可能没有必要这样做。