Хорошо, немного обобщив:
У вас есть список данных data
, и вы хотите работать с этими данными асинхронно. Предполагая, что операция одинакова для всех записей в вашем списке, вы можете сделать это:
data = [1, 2, 3, 4] # Example data
operation = -> (data_entry) { data * 2 } # Our operation: multiply by two
results = data.map{ |e| Thread.new(e, &operation) }.map{ |t| t.value }
Разобрав его:
data = [1, 2, 3, 4]
Это может быть что угодно, от идентификаторов базы данных до URI. Использование чисел для простоты здесь.
operation = -> (data_entry) { data * 2 }
Определение лямбды, которая принимает один аргумент и выполняет некоторые вычисления на нем. Это может быть вызов API, запрос SQL или любая другая операция, выполнение которой занимает некоторое время. Опять же, для простоты я просто умножаю числа на 2.
results =
Этот массив будет содержать результаты всех асинхронных операций.
data.map{ |e| Thread.new(e, &operation) }...
Для каждой записи в наборе данных порождает поток, который запускает operation
и передает запись в качестве аргумента. Это аргумент data_entry
в лямбде.
...map{ |t| t.value }
Извлечение значения из каждого потока. Это будет ждать завершения потока, поэтому к концу этой строки все ваши данные будут там.
Лямбда
Лямбды - это просто прославленные блоки, которые вызывают ошибку, если вы передаете неверное количество аргументов. Синтаксис -> (arguments) {code}
является просто синтаксическим сахаром для Lambda.new { |arguments| code }
.
Когда метод принимает блок, такой как Thread.new { do_async_stuff_here }
, вы также можете передать объект Lambda или Proc с префиксом &
, и он будет обрабатываться таким же образом.