Unordered responses when batching elm/http commands with Cmd.batch
0 reputation · 29 Mar 2020, 21:58 UTC
0 reputation · 29 Mar 2020, 21:58 UTC
Determine whether issuing several elm/http commands through Platform.Cmd.batch produces concurrent, ordered, or implementation-defined response delivery in the Elm runtime.
The application pins elm/http 2.x, but the exact minor version is not yet confirmed. Platform.Cmd.batch combines commands into a single command that runs them all, yet official documentation does not state ordering or interleaving guarantees for the resulting effects. Because the Elm runtime processes one message at a time, each HTTP response becomes a separate Msg delivered through the sequential update loop, so a burst of responses may land in an order that differs from the command list. No production incident or observed latency is being reported; this is a design question about documented behavior.
34775 reputation · 30 Mar 2020, 09:00 UTC
Does Cmd.batch guarantee dispatch order? No. The Elm runtime treats batched commands as independent effects; underlying JavaScript HTTP calls may be issued in any order or concurrently.
Are response Msgs guaranteed to arrive in request order? No. Each HTTP response becomes a separate message scheduled by the browser's event loop. Network latency and server processing time determine arrival order, not the original command list.
Is Task.sequence the only documented way to enforce strict sequencing? Yes. Converting each Http.request to a Task via Http.toTask (available since elm/http 2.0.0), sequencing them with Task.sequence, and performing the result via Task.perform yields ordered dispatch and ordered delivery.
The Elm runtime processes one message at a time through the sequential update loop. Cmd.batch merely combines multiple commands into a single command value; it does not impose a scheduling discipline on the JavaScript side. When you batch three Http.get calls, the runtime hands all three to the JavaScript HTTP layer, which typically fires them concurrently. Responses return as independent browser events, each queued as a separate message. The update function then runs once per response, but the sequence of those invocations reflects network timing, not your source list order.
If correctness depends on response order (e.g., request B uses data from request A), refactor to Task.sequence:
requests : List (Http.Request ResponseType)
requests = [ reqA, reqB, reqC ]
batchTask : Task Http.Error (List ResponseType)
batchTask = Task.sequence (List.map Http.toTask requests)
-- In update:
Task.perform BatchResult batchTask
This chains the tasks so each request starts only after the previous one completes, guaranteeing both dispatch and delivery order.
Http.get requests to a test endpoint (e.g., httpbin.org/delay/1 with varying delays) and logs the arrival order of the resulting messages.Cmd.batch.Task.sequence (List.map Http.toTask requests) |> Task.perform BatchResult and verify responses now arrive in request order.Http.toTask and Task.sequence examples.These semantics have been consistent since Cmd.batch was introduced in Elm 0.17. The exact minor version of elm/http 2.x does not change them; Http.toTask exists in all 2.x releases. If your application pins an older 1.x version, the same lack of guarantees applies, but Http.toTask is unavailable—you would need to wrap requests in Task.perform manually.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.