We can use Promise.race to wait for the first arrived result on the thenable
chain. The Task module doesn't seem to support it yet, Task.sequence is only the equivalent to Promise.all.
Non-thenable Solution demo:
import Process
import Task
init () =
( Nothing, Cmd.batch [ after 2 "2nd", after 1 "1st" ] )
after seconds name =
Process.sleep (1000 * seconds)
|> Task.map (always name)
|> Task.perform Done
type Msg
= Done String
update (Done name) model =
case model of
Nothing ->
( Debug.log name <| Just name, Cmd.none )
_ ->
( Debug.log name model, Cmd.none )
main =
Platform.worker
{ init = init
, update = update
, subscriptions = always Sub.none
}
Run it, output as expected:
1st: Just "1st"
2nd: Just "1st"
Promise.race
as a self-contained function requires maintaining local state to track whether or not it's been resolved already, which as you probably know isn't possible in Elm.
But you can accomplish the same thing relatively easily by tracking the state in the model yourself. Here's an example using Maybe
to track whether we've received a response:
type Thing =
...
getThings : String -> Task Never (List Thing)
getThings url =
...
type alias Model =
{ things : Maybe (List Thing) }
type Msg
= GotThings (List Thing)
init =
( { things = Nothing }
, Cmd.batch
[ Task.perform GotThings (getThings "https://a-server.com/things")
, Task.perform GotThings (getThings "https://a-different-server.com/things")
]
)
update msg model =
case msg of
GotThings things ->
case model.things of
Nothing ->
( { things = Just things }, Cmd.none )
Just _ ->
-- if we have already received the things, ignore any subsequent requests
( model, Cmd.none )
view model =
...