在 ELM 中链接 http 请求并合并 json 响应



我已经成功地在ELM中触发了一个简单的http请求,并将JSON响应解码为ELM值 - [https://stackoverflow.com/questions/43139316/decode-nested-variable-length-json-in-elm]

我现在面临的问题——

如何链接(并发首选)两个 http 请求并将 json 合并到我的新(更新)模型中。注意 - 请参阅更新的命令.elm

用于访问远程数据的软件包 - krisajenkins/remotedata http://package.elm-lang.org/packages/krisajenkins/remotedata/4.3.0/RemoteData

我的代码的 Github 存储库 - https://github.com/areai51/my-india-elm

以前的工作代码 -

模型.elm

type alias Model =
{ leaders : WebData (List Leader)
}
initialModel : Model
initialModel =
{ leaders = RemoteData.Loading
}

主榆树

init : ( Model, Cmd Msg )
init =
( initialModel, fetchLeaders )

命令.elm

fetchLeaders : Cmd Msg
fetchLeaders =
Http.get fetchLeadersUrl leadersDecoder
|> RemoteData.sendRequest
|> Cmd.map Msgs.OnFetchLeaders

fetchLeadersUrl : String
fetchLeadersUrl =
"https://data.gov.in/node/85987/datastore/export/json"

Msgs.elm

type Msg
= OnFetchLeaders (WebData (List Leader))

更新.elm

update msg model =
case msg of
Msgs.OnFetchLeaders response ->
( { model | leaders = response }, Cmd.none )

更新的代码 -(需要有关 Command.elm 的帮助)

模型.elm

type alias Model =
{ lsLeaders : WebData (List Leader)
, rsLeaders : WebData (List Leader)           <------------- Updated Model
}

initialModel : Model
initialModel =
{ lsLeaders = RemoteData.Loading
, rsLeaders = RemoteData.Loading
}

主榆树

init : ( Model, Cmd Msg )
init =
( initialModel, fetchLeaders )

命令.elm

fetchLeaders : Cmd Msg
fetchLeaders =                                  <-------- How do I call both requests here ? And fire separate msgs
Http.get fetchLSLeadersUrl lsLeadersDecoder    <----- There will be a different decoder named rsLeadersDecoder
|> RemoteData.sendRequest
|> Cmd.map Msgs.OnFetchLSLeaders

fetchLSLeadersUrl : String
fetchLSLeadersUrl =
"https://data.gov.in/node/85987/datastore/export/json"

fetchRSLeadersUrl : String                     <------------------ New data source
fetchRSLeadersUrl =
"https://data.gov.in/node/982241/datastore/export/json"

Msgs.elm

type Msg
= OnFetchLSLeaders (WebData (List Leader))
| OnFetchRSLeaders (WebData (List Leader))         <-------- New message

更新.elm

update msg model =
case msg of
Msgs.OnFetchLSLeaders response ->
( { model | lsLeaders = response }, Cmd.none )
Msgs.OnFetchRSLeaders response ->                  <--------- New handler
( { model | rsLeaders = response }, Cmd.none )

触发两个并发请求的方法是使用Cmd.batch

init : ( Model, Cmd Msg )
init =
( initialModel, Cmd.batch [ fetchLSLeaders, fetchRSLeaders ] )

不能保证哪个请求会首先返回,也不能保证它们都会成功。例如,一个可能失败,而另一个成功。

您提到要合并结果,但您没有说明合并将如何工作,所以我只是假设您想将领导者列表附加到一个列表中,如果您只需要处理单个RemoteData值而不是多个值,这对您的应用程序很有用。

您可以使用mapandMap将多个RemoteData值与自定义函数合并在一起。

mergeLeaders : WebData (List Leader) -> WebData (List Leader) -> WebData (List Leader)
mergeLeaders a b =
RemoteData.map List.append a
|> RemoteData.andMap b

请注意,我在那里使用List.append。这实际上可以是任何采用两个列表并随心所欲地合并它们的函数。

如果您更喜欢应用式编程风格,可以将上述内容转换为以下中缀版本:

import RemoteData.Infix exposing (..)
mergeLeaders2 : WebData (List Leader) -> WebData (List Leader) -> WebData (List Leader)
mergeLeaders2 a b =
List.append <$> a <*> b

根据有关andMap的文档(在其示例中使用结果元组而不是附加列表):

仅当其所有子元组都成功时,最后一个元组才会成功。如果它的任何子项仍在加载中,则它仍处于正在加载状态。如果任何子项失败,则错误是最左边的失败值。

最新更新