我有这个管道
events
|> Task.async_stream(&expensive_func/1)
|> Enum.to_list
哪个返回此数据:
[ok: {item}, ok: {item} ... ]
所以,为了只包含一组项目,[item, item]
我将其像这样进行后期处理:
events
|> Task.async_stream(&expensive_func/1)
|> Enum.to_list
|> Enum.map(fn {:ok, event} -> event end)
有没有更优雅的方式做到这一点?
答案 0 :(得分:2)
另一种方式:
events
|> Task.async_stream(&expensive_func/1))
|> Enum.map(&(elem(&1,1)))
警告:由于我们直接访问每个Task
返回的元组的第二个元素,因此不会进行检查以确保Task
已正确运行。您可以在:ok
上添加匹配的模式来解决该问题(如您在问题中所做的那样)。
答案 1 :(得分:2)
这里要考虑的主要事情是:任务可能会失败。如果想要的行为只是丢弃它们,只需直接使用Task.async_stream/3
示例中的示例,然后明确丢弃它们
events
|> Task.async_stream(&expensive_func/1)
|> Enum.reduce([], fn
{:ok, event}, acc -> [event | acc]
_, acc -> acc # discard failures
end)
|> Enum.reverse()
另一种选择是依靠任务的返回值(如果失败则返回例如nil
),则可能直接使用Keyword.values/1
:
events
|> Task.async_stream(&expensive_func/1)
|> Enum.to_list()
|> Keyword.values()
FWIW,如果至少有一项任务因您的函数无法处理MatchError
而失败,那么您的原始解决方案将引发:error
。