Suppose I have a controlled Elmish form:
type Model =
{
Query : string
IsLoading : bool
Result : Result<QueryResults, string> option
}
type Message =
| UpdateQuery of string
| ReceivedResults of Result<QueryResults, string>
let update message model =
match message with
| UpdateQuery query ->
let nextModel =
{
model with
Query = query
IsLoading = true
}
let cmd =
Cmd.OfAsync.result (async {
let! results = Api.tryFetchQueryResults query
return ReceivedResults results
})
nextModel, cmd
| ReceivedResults results ->
{
model with
IsLoading = false
Results = Some results
}, Cmd.none
Every time model.Query
changes, it sends off an async
request. However, if there is already a request in progress, I would like that to be cancelled and replaced with the new one.
What is a good way to do this in Elmish?
There is nothing built in to support cancellation of the underlying XMLHttpRequest
.
We can, however, build some small machinery that will support cancellation-like functionality:
First, augment your Model
with information about the current pending query, and your Message
with a link (a simple Guid
will do) to that query
open System
type Model =
{
Query : string
IsLoading : bool
Result : Result<QueryResults, string> option
PendingQuery: Guid option
}
type Message =
| UpdateQuery of string
| ReceivedResults of Guid * Result<QueryResults, string>
Next, provide these pieces of data in your update
function
| UpdateQuery query ->
let correlationId = Guid.NewGuid()
let nextModel =
{
model with
Query = query
IsLoading = true
PendingQuery = Some correlationId
}
let cmd =
Cmd.OfAsync.result (async {
let! results = Api.tryFetchQueryResults query
return ReceivedResults (correlationId, results)
})
nextModel, cmd
Finally, check the pending query when receiving data from the server and ignore stuff not matching the link
| ReceivedResults (correlationId, results) ->
match model.PendingQuery with
| Some id when id = correlationId ->
{
model with
IsLoading = false
PendingQuery = None
Result = Some results
}, Cmd.none
| _ -> model, Cmd.none
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.