HTTP
从互联网其他位置获取信息往往很有帮助。
例如,假设我们希望加载沃尔特·李普曼的《公众舆论》的全文。这本书于 1922 年出版,从历史角度阐述了大众媒体的兴起及其对民主的影响。在此,我们将重点介绍如何使用 elm/http
包将这本书载入到我们的程序中!
点击蓝色的“编辑”按钮,即可在线编辑器中查看此程序。在完全显示这本书之前,您可能会在屏幕上看到“加载中...”这一提示。立即点击蓝色按钮!
import Browser
import Html exposing (Html, text, pre)
import Http
-- MAIN
main =
Browser.element
{ init = init
, update = update
, subscriptions = subscriptions
, view = view
}
-- MODEL
type Model
= Failure
| Loading
| Success String
init : () -> (Model, Cmd Msg)
init _ =
( Loading
, Http.get
{ url = "https://elm-lang.org/assets/public-opinion.txt"
, expect = Http.expectString GotText
}
)
-- UPDATE
type Msg
= GotText (Result Http.Error String)
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
GotText result ->
case result of
Ok fullText ->
(Success fullText, Cmd.none)
Err _ ->
(Failure, Cmd.none)
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
-- VIEW
view : Model -> Html Msg
view model =
case model of
Failure ->
text "I was unable to load your book."
Loading ->
text "Loading..."
Success fullText ->
pre [] [ text fullText ]
此部分的一些内容应该让人熟悉,因为它们来自 Elm 架构先前的示例。我们仍然有应用程序的 Model
。我们仍然有一个对消息做出反应的 update
。我们仍然有一个在屏幕上显示所有内容的 view
函数。
新部分通过 init
和 update
中的一些更改,以及 subscription
的添加,扩展了我们之前看到的核心模式。
init
init
函数描述如何初始化我们的程序
init : () -> (Model, Cmd Msg)
init _ =
( Loading
, Http.get
{ url = "https://elm-lang.org/assets/public-opinion.txt"
, expect = Http.expectString GotText
}
)
我们始终必须生成初始 Model
,但现在我们还会生成我们希望立即执行的某个操作的 命令。该命令将最终生成一个输入到 update
函数的 Msg
。
我们的书籍网站从 Loading
状态启动,我们希望获取我们书籍的全文。在使用 Http.get
执行 GET 请求时,我们指定要获取数据的 url
,并且指定我们 expect
该数据是什么。因此,在我们的案例中,url
指向 Elm 网站上的某些数据,并且我们expect
该数据是我们可以显示在屏幕上的一大串 String
。
Http.expectString GotText
行表示的不仅仅是我们expect
一个String
。它还表示当我们收到响应时,它应转换为GotText
消息
type Msg
= GotText (Result Http.Error String)
-- GotText (Ok "The Project Gutenberg EBook of ...")
-- GotText (Err Http.NetworkError)
-- GotText (Err (Http.BadStatus 404))
请注意,我们正在使用几节前的Result
类型。这使我们能够充分考虑update
函数中的可能失败。说到update
函数...
注意:如果您想知道为什么
init
是一个函数(以及我们为什么忽略参数),我们将在即将到来的 JavaScript 交互操作章节中讨论它!(预览:该参数允许我们在初始化时从 JS 中获取信息。)
update
我们的update
函数也返回了更多信息
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
GotText result ->
case result of
Ok fullText ->
(Success fullText, Cmd.none)
Err _ ->
(Failure, Cmd.none)
查看类型签名,我们看到我们不仅仅返回一个更新的模型。我们还生成了一个命令,告诉 Elm 要做什么。
继续实现,我们像往常一样对消息进行模式匹配。收到GotText
消息时,我们检查 HTTP 请求的Result
,并根据请求是成功还是失败来更新模型。新部分是我们还提供了一个命令。
因此,如果我们成功获取了全文,我们说Cmd.none
表示没有更多工作要做。我们已经得到了全文!
如果出现错误,我们也会说Cmd.none
并且放弃。这本书的文字没有加载。如果我们要更花哨一些,我们可以对 Http.Error
进行模式匹配,并在超时或其他情况下重试请求。
这里的意思是,无论我们如何决定更新我们的模型,我们都可以自由地发出新的命令。我需要更多数据!我想要一个随机数!等
subscription
这个程序中另一个新东西是subscription
函数。它允许你查看Model
并决定你想订阅哪些信息。在我们的示例中,我们说Sub.none
表示我们不需要订阅任何内容,但我们很快就会看到一个想要订阅当前时间的时钟示例!
摘要
当我们使用Browser.element
创建程序时,我们会设置这样的系统
我们能够从init
和update
发出命令。这允许我们随时做一些事情,比如发出 HTTP 请求。我们还可以订阅有趣的信息。(我们稍后会看到订阅的示例!)