Elm:如何在后续请求中使用来自一个 HTTP 请求的数据

Elm: How to use data from one HTTP request in subsequent requests

我是 Elm 的新手,刚刚阅读了文档 (https://guide.elm-lang.org/)。我正在修改那里的一个例子并四处玩耍。 我想要做的是点击一个端点,它会给我一个 ID 列表。稍后我想用这些 ID 分别访问另一个端点并显示结果。

https://hacker-news.firebaseio.com/v0/topstories.json - 此端点有一个 ID 列表。

https://hacker-news.firebaseio.com/v0/item/[ID].json - 此端点将提供给定 ID 的故事的详细信息。

到目前为止,我可以单独获取所有 ID 的列表,并且可以单独获取每个故事(硬编码 ID)并显示它们。但我在这里想要实现的是

我不知道该怎么做。非常感谢任何帮助。

谢谢

您可以在处理来自第一个终结点的响应时触发第二个请求。类似于:

type Msg
    = GotIds (Result Http.Error (List Int))
    | GotStory (Result Http.Error (String))


update : Msg -> Model -> (Model,  Cmd Msg)
update msg model =
    case msg of
        GotIds result ->          
            case result of
                Ok (first::rest) -> 
                    ({ model | ids = first::rest }, getStory first)
                Ok _ ->
                    (model, Cmd.none)
                Err _ ->
                    ({ model | story = "ERROR"}, Cmd.none)
        GotStory result ->    
            ({model | story = Result.withDefault "None" result}, Cmd.none)

如果你想同时触发多个Cmd,你可以使用Cmd.batch

Here is an Ellie 从第一个请求中获取 ID,然后获取第一个 ID 的标题。

您需要为每个 post 创建自定义类型和 decoder

为了post真实,这里是 Ellie 的所有代码:

module Main exposing (main)

import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)
import Http
import Json.Decode exposing (Decoder, field, int, list, string )

type alias Model =
    { ids : List Int 
    , story : String
    }


initialModel : Model
initialModel =
    { ids = [] 
    , story = "None"
    }


type Msg
    = GotIds (Result Http.Error (List Int))
    | GotStory (Result Http.Error (String))


update : Msg -> Model -> (Model,  Cmd Msg)
update msg model =
    case msg of
        GotIds result ->          
            case result of
                Ok (first::rest) -> 
                    ({ model | ids = first::rest }, getStory first)
                Ok [] ->
                    (model, Cmd.none)
                Err _ ->
                    ({ model | story = "ERROR"}, Cmd.none)
        GotStory result ->    
            ({model | story = Result.withDefault "None" result}, Cmd.none)


view : Model -> Html Msg
view model =
    div []
        [ text model.story
        ]


main : Program () Model Msg
main =
    Browser.element
        { init = init
        , view = view
        , update = update
        , subscriptions = (\_ -> Sub.none)
        }
        
init : () -> (Model, Cmd Msg)
init flags =
    (initialModel, getIds)
        
getIds : Cmd Msg
getIds =
  Http.get
    { url = "https://hacker-news.firebaseio.com/v0/topstories.json"
    , expect = Http.expectJson GotIds (list int)
    }

getStory : Int ->  Cmd Msg
getStory id =
  Http.get
    { url = "https://hacker-news.firebaseio.com/v0/item/" ++ String.fromInt id ++ ".json"
    , expect = Http.expectJson GotStory (field "title" string)
    }