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

时间:2017-04-04 11:12:41

标签: json http elm

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

问题我现在面对 -

如何链接(并发首选)两个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

以前的工作代码 -

Models.elm

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

initialModel : Model
initialModel =
    { leaders = RemoteData.Loading
    }

Main.elm

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

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"

Msgs.elm

type Msg
    = OnFetchLeaders (WebData (List Leader))

Update.elm

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

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

Models.elm

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


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

Main.elm

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

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"

Msgs.elm

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

Update.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 )

1 个答案:

答案 0 :(得分:3)

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

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

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

你提到要合并结果,但是你没有说合并是如何工作的,所以我假设你想把领导者列表放在一个列表中,这对于如果你只需要处理一个RemoteData值而不是多个值,那么你的应用程序就可以了。

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

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上的文档(在其示例中使用结果元组而不是附加列表):

  

最终元组只有在所有孩子都成功的情况下才能成功。如果其中任何一个孩子仍在加载,它仍然在加载。如果任何一个孩子失败,那么错误就是最左边的失败值。