2016-07-07 64 views
1

我想了解過去一週的榆樹,並希望通過調用官方Hacker News API來構建簡單的Hacker News客戶端。Elm:製作連續的網絡請求

我打電話給https://hacker-news.firebaseio.com/v0/topstories.json以獲取將返回故事ID數組的頂級故事。一旦我有了Id,我需要對https://hacker-news.firebaseio.com/v0/item/進行後續調用。[/ * Id在這裏* /]。json獲取每個故事項目的詳細信息。

我有一個Main.elm文件,它將獲取頂級故事列表。

type Msg = Request 
    | RequestSuccess (List Int) 
    | RequestFail Http.Error 


update : Msg -> Model -> (Model, Cmd Msg) 
update msg model = 
case msg of 
    Request -> 
    (model, getTopNews) 
    RequestSuccess list-> 
    (Model list, Cmd.none) 
    RequestFail error-> 
    (Model [], Cmd.none) 

下一部分是我困惑的地方,爲每個返回的項目提取詳細信息。我也有一個NewsItem組件來顯示每個新聞項目的細節。

如何解決這個問題,通過在NewsItem組件(子組件)中創建聯合類型來獲取細節?如果多數民衆贊成如何我應該這樣做..

  1. 我怎麼能從MainItem的第一個API調用完成後調用從NewsItem組件的提取細節API?
  2. 或者我在這裏錯過了一些明顯的東西?這根本不是正確的方法?

You can see what I have tried so far here.

回答

1

這裏是我的建議。它假設您將獨立加載每個NewsItem,並且它們也都可以獨立運行。如果情況並非如此,那麼我們肯定會想出一些對您更好的方法。

1)表示您的NewsItem不僅僅是一條記錄,而是一個包裹在一個類型中的記錄,表示加載細節失敗的可能性。有關更多信息,請參閱http://blog.jenkster.com/2016/06/how-elm-slays-a-ui-antipattern.html

module NewsItem 

-- imports and such 

type Model = Loading | Success NewsItem | Failure Http.Error 

2)撰寫您NewsItem模塊中的init函數接受一個Int並返回(NewsItem.Model, Cmd NewsItem.Msg)

init : Int -> (Model, Cmd Msg) 
init newsItemId = 
    (Loading 
    , getNewsItem newsItemId |> Task.perform GetItemFailure GetItemSuccess 
    ) 

3)在你的Main模塊,一旦你取出你的ID列表,使用您的init函數將它們映射到List (NewsItem.Model, Cmd NewsItem.Msg),並使用Elm體系結構的技術將它們作爲子模型存儲在父模型中。我建議將它們存儲爲將ID映射到子模型的Dict Int NewsItem.Model

RequestSuccess list -> 
    let 
     children = 
      list |> List.map (\id -> (id, NewsItem.init id)) 

     childModels = 
      children 
       |> List.map (\(id, (model, cmd)) -> (id, model)) 
       |> Dict.fromList 

     childCmds = 
      children 
       |> List.map (\(id, (model, cmd)) -> Cmd.map (NewsItemMsg id) cmd) 
       |> Cmd.batch 
    in 
     (Model childModels, childCmds)