如何在Elm中合并多个效果?

时间:2017-07-30 02:10:21

标签: parallel-processing elm

我有一个关于合并多个效果的问题。我的目标是并行运行N个命令(例如Random或Http),然后合并结果并启动更新。可以认为它是N骰子Elm Architecture Dice exercises的延伸。

我知道您可以使用Task.map2Task.sequence执行此操作,但我正在专门寻找并行执行。

Cmd.batch听起来像我想要的并行部分,但我无法弄清楚如何合并执行的结果。

这是my full Elm code 这里how I'm guessing at transforming it to act in parallel(没有工作)。

对于它的价值,在JS中我用Promise.all

完成了这个

Promise.all([promise1, promise2, …]).then(resultsList => …)

在此主题上找不到任何关于此主题的内容,除此之外,它回避了问题:How to perform multiple Http requests (Tasks) in bulk in Elm lang,这避免了多重影响:How do I add a second die to this elm effects example?。希望情况仍然如此:Is there parallelism in Elm?(2015年答案为否)。

2 个答案:

答案 0 :(得分:1)

Process.spawn将允许您启动运行时可能交错的多个任务,但是似乎没有办法以单Msg a结尾{{{ 1}}是一些并行任务的综合结果。

Future Plans下的处理页面上的注释似乎与您的问题相关。

如果您想进一步探索现在可能发生的事情以及a的行为,我已经创建了一个extension of the more-cats HTTP example app,从{移植{@ 3}}中的一些助手{3}}(尚未更新0.18)。

答案 1 :(得分:1)

使用Elm Architecture,您可以使用Cmd.batch一次启动一系列任务,但是当结果准备就绪时,它们将在更新函数中以单Msg个值的形式出现,并且没有保证的顺序。

因此,(至少从榆木0.18开始),你需要自己处理“合并”结果,因为你发射的Msgs将逐一进入。在你的骰子示例中,您需要一个Msg构造函数来设置特定数组索引处的骰子值(在此示例中,我使用Array而不是List,因为您将设置很多索引):

type Msg
    = Roll
    | NewFaceAt Int Int

现在您只需处理NewFaceAt案例中的update构造函数:

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Roll ->
            ( model
            , Cmd.batch
                (Array.toIndexedList model.dice
                    |> List.map (\( i, _ ) -> Random.generate (NewFaceAt i) (Random.int 1 6))
                )
            )

        NewFaceAt index newFace ->
            ( { model | dice = Array.set index newFace model.dice }, Cmd.none )

Here is a working example of the above on ellie-app.com

如果您想更接近Promise.all([...]).then(...)示例,则必须在模型上烘焙某种状态标记,每次收到NewFaceAt时都会更新。例如,您的骰子可能是Maybe Int的列表,然后当您滚动时,将它们全部设置为Nothing,并且当骰子值进入时,您将它们设置为Just value然后检查查看是否填写了所有骰子值。您可以编写视图,以便在结果仍未知时显示“加载”消息,并且仅在所有结果都显示时显示图像。Here is an example that waits until all results are ready(授予,它发生得如此之快以至于您赢了看不到加载屏幕;处理多个Http请求时效果更明显。)