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

Kau*_*tav 1 json http elm

我已经成功触发了ELM中的简单http请求,并将JSON响应解码为ELM值- [/sf/ask/3019752151/]

我现在面临的问题-

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

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

我的代码的Github回购-https: //github.com/areai51/my-india-elm

以前的工作代码-

模型

type alias Model =
    { leaders : WebData (List Leader)
    }

initialModel : Model
initialModel =
    { leaders = RemoteData.Loading
    }
Run Code Online (Sandbox Code Playgroud)

Main.elm

init : ( Model, Cmd Msg )
init =
    ( initialModel, fetchLeaders )
Run Code Online (Sandbox Code Playgroud)

Commands.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"
Run Code Online (Sandbox Code Playgroud)

邮件

type Msg
    = OnFetchLeaders (WebData (List Leader))
Run Code Online (Sandbox Code Playgroud)

更新文件

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

更新的代码- (需要Commands.elm的帮助)

模型

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


initialModel : Model
initialModel =
    { lsLeaders = RemoteData.Loading
    , rsLeaders = RemoteData.Loading
    }
Run Code Online (Sandbox Code Playgroud)

Main.elm

init : ( Model, Cmd Msg )
init =
    ( initialModel, fetchLeaders )
Run Code Online (Sandbox Code Playgroud)

Commands.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"
Run Code Online (Sandbox Code Playgroud)

邮件

type Msg
    = OnFetchLSLeaders (WebData (List Leader))
    | OnFetchRSLeaders (WebData (List Leader))         <-------- New message
Run Code Online (Sandbox Code Playgroud)

更新文件

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

        Msgs.OnFetchRSLeaders response ->                  <--------- New handler
            ( { model | rsLeaders = response }, Cmd.none )
Run Code Online (Sandbox Code Playgroud)

Cha*_*ert 5

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

init : ( Model, Cmd Msg )
init =
    ( initialModel, Cmd.batch [ fetchLSLeaders, fetchRSLeaders ] )
Run Code Online (Sandbox Code Playgroud)

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

您提到要合并结果,但没有说明合并的工作方式,因此我假设您要将领导者列表附加到一个列表中,如果对您只需要处理一个RemoteData值,而不要处理多个值。

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

mergeLeaders : WebData (List Leader) -> WebData (List Leader) -> WebData (List Leader)
mergeLeaders a b =
    RemoteData.map List.append a
        |> RemoteData.andMap b
Run Code Online (Sandbox Code Playgroud)

请注意,我在这里使用List.append。这实际上可以是任何需要两个列表并将其合并的函数,但是请您选择。

如果您喜欢应用风格的编程,可以将以上内容翻译为以下中缀版本:

import RemoteData.Infix exposing (..)

mergeLeaders2 : WebData (List Leader) -> WebData (List Leader) -> WebData (List Leader)
mergeLeaders2 a b =
    List.append <$> a <*> b
Run Code Online (Sandbox Code Playgroud)

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

仅当其所有子级都成功时,最后的元组才成功。如果它的任何子项仍在加载中,它仍在加载中。如果任何子代失败,则错误是最左边的失败值。