【发布时间】:2018-02-16 00:30:24
【问题描述】:
我有相当多的使用 React 构建 Web 应用程序的经验,但我想学习 Elm。几天来,我一直在努力解决 HTTP 请求问题。
我在 localhost:8080 上运行 Elm 应用程序,在 localhost:8081 上运行我的支持 API。每当我发出 HTTP 请求(我尝试过 GET 和 POST 请求)时,我都会收到 NetworkError。我一直在研究 Elm JSON 解码器,并认为这可能是我的问题所在,但我尝试从我的服务器发送简单字符串并在我的 Elm 应用程序中使用 Decode.string 解码器,但我仍然得到 NetworkError。
这是我的代码目前的样子:
Commands.elm
module Commands exposing (..)
import Models exposing (..)
import Msg exposing (..)
import Http
import Json.Decode as Decode
import Json.Encode as Encode
createTempUser : Model -> Cmd Msg
createTempUser model =
let
tempUserBody =
[ ( "firstname", Encode.string model.firstname )
, ( "lastname", Encode.string model.lastname )
, ( "phone", Encode.string model.phone )
]
|> Encode.object
|> Http.jsonBody
url =
myAPIUrl ++ "/endpoint"
contentType = Http.header "Content-type" "text/plain"
post =
Http.request
{ method = "POST"
, headers = [contentType]
, url = url
, body = tempUserBody
, expect = Http.expectJson decodeApiResponse
, timeout = Nothing
, withCredentials = False
}
in
Http.send Msg.TempUserCreated post
decodeApiResponse : Decode.Decoder ApiResponse
decodeApiResponse =
Decode.map4 ApiResponse
(Decode.at ["status"] Decode.int)
(Decode.at ["message"] Decode.string)
(Decode.at ["created"] Decode.int)
(Decode.at ["error"] Decode.string)
myAPIUrl : String
myAPIUrl = "http://localhost:8081"
Models.elm
module Models exposing (..)
type alias ApiResponse =
{ status: Int
, message: String
, created: Int
, error: String
}
Msg.elm
module Msg exposing (..)
import Navigation exposing (Location)
import Models exposing (..)
import Http
type Msg
= ChangeLocation String
| OnLocationChange Location
| CreateTemporaryUser
| TempUserCreated ( Result Http.Error ApiResponse )
更新.elm
module Update exposing (..)
import Msg exposing (Msg)
import Models exposing (..)
import Routing exposing (..)
import Commands exposing (..)
import Navigation
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Msg.ChangeLocation path ->
( { model | changes = model.changes + 1 }, Navigation.newUrl path )
Msg.OnLocationChange location ->
( { model | error = "", route = parseLocation(location) }, Cmd.none )
Msg.CreateTemporaryUser ->
( model, createTempUser model )
Msg.TempUserCreated (Ok res) ->
update (Msg.ChangeLocation signupCodePath) { model | httpResponse = toString(res) }
Msg.TempUserCreated (Err err) ->
( { model | error = toString(err) }, Cmd.none )
Chrome 的网络开发工具显示响应如下
{"status":200,"message":"Successfully inserted temporary
user","created":1518739596447,"error":""}
我认为这可能是所有相关代码,但如果您需要查看更多内容,我会进行更新,包括请求的代码。我承认我对 Elm Json.Decode 库没有完全了解,但我的印象是,如果这是问题所在,我会收到包含额外上下文的 UnexpectedPayload 错误。
【问题讨论】:
-
那么,Chrome Devtools 显示您实际上得到了成功的响应,但 Elm 报告了 NetworkError?你怎么知道你收到了 NetworkError?
-
在我的更新 Msg.TempUserCreated (Err err) 中,我将错误字符串保存到我的模型中,并在应用程序视图中显示我的模型,因此我可以看到模型更新为 model.error =当我提出请求时出现“NetworkError”
-
我自己加载了 repo。由于我没有在
:8081上运行 API 服务器,因此每个请求都失败了,正如您所料。但我实际上从未在模型中看到NetworkError!模型中的错误始终为空。我添加了Debug.log,果然,我实际上得到了NetworkError。如果没有 API 服务器,我可能无法重现错误。 -
我看到你在一些 json 对象中返回 200,但是你在 http 标头本身中得到了 200?
-
@SimonH 好问题,服务器实际上可能正在发送不同的状态。虽然理论上不成功状态应该导致
BadStatus错误而不是NetworkError