Asynchronous Array Mapping in Ruby
EventMachine is great, but may require a few fights to get started.
Recently, I wanted to be able to get the sizes of each image in an array using FastImage. It’s fast, but it’s not that fast when you’ve got tens or hundreds of images you’re trying to size at once.
What I needed was an asynchronous map method for Arrays, like this:
images = [ "http://example.com/one.png", "http://example.com/two.png", ... ]
images.async_map { |img| FastImage.size(img) }
EventMachine did not make this easy. After some fighting, here’s what I came up with:
class Array
def async_map(&block)
results = nil
EventMachine.run do
operation = proc { |item, iter|
EventMachine.defer(proc { block.call(item) }, proc { |r| iter.return(r) })
}
callback = proc { |rs|
results = rs
EventMachine.stop
}
EventMachine::Iterator.new(self, length).map(operation, callback)
end
results
end
end
It works (10x speed increase!), but I’d like to believe that there’s got to be an easier way to do this.