Elm Json 请求不工作?

Elm Json request not working?

在 Elm 中,您可以使用 Json.decodeHttp package 来请求 json 数据。我的尝试是定期查找电子邮件 ( from this url )。计时器操作确实有效(我用一个简单的计数器尝试过)。

我参考了this example and

现在的类型:

type alias Email = { title: String, ... }

type Action =
    NoAction
    | TickCounter -- TODO rem
    | AddEmails (List Email)

然后主要+状态+动作...

main: Signal Html
main = Signal.map (view actions.address) state

state: Signal Model
state = Signal.foldp update makeEmptyModel input

-- handle inputs (merging signals)
input : Signal Action
input =
    Signal.mergeMany
    [ actions.signal
    -- , other actions
    , Signal.map checkForNewMails (Time.every (Time.minute / 6.0) ) -- TODO precise timer (quick test)
    ]

actions: Signal.Mailbox Action
actions = Signal.mailbox NoAction

update: Action -> Model -> Model
update action model =
case action of
    NoAction -> model
    TickCounter -> { model | count = model.count + 1 }
    AddEmails newMails -> { model | emails = newMails }


checkForNewMails: Time -> Action
checkForNewMails t =
    let mails = startGettingEmailData
    in TickCounter -- TODO replace with AddEmails using mails

TickCounter是一个Action,我用它来测试我的计时操作。但问题是startGettingEmailData。它使用下一个片段,但它不会触发任何 JSON 请求(我已经通过控制台检查过)。一旦这个问题得到解决,我就可以将 mails 转换为一个动作,这样我就可以在模型中添加电子邮件。

-- url to json
jsonUrl = "https://dl.dropboxusercontent.com/u/14070433/temp.json"

-- get emails
startGettingEmailData: Task Http.Error (List Email)
startGettingEmailData = Http.get emailJsonDecoder jsonUrl 

emailJsonDecoder: Json.Decoder (List Email)
emailJsonDecoder =
    let makeEmail = Json.object4
            (\ti fr da bo -> makeNewEmail -1 ti fr da bo )
            ("title" := Json.string)
            ("from" := Json.string)
            ("date" := Json.string)
            ("body" := Json.string)
    in
        "emails" := Json.list makeEmail

我的代码有问题吗?如果没有,那么有没有办法检查 Http.Error 内容? (也许问题不在我的代码,而在网络,但我可以通过浏览器访问保管箱文件...)

您的 checkForNewMails 代码实际上并未对 mails 执行任何操作,因此它永远不会被调用。 let 语句不进行任何调用,它只允许您在更大的函数体内定义一次性函数。由于 in 部分只是 returns TickCounter,那么这意味着此函数只 returns TickCounter 并且什么都不做。

此外,startGettingEmailData 返回 Task,这意味着它仅在端口中时被调用。你不能在只有 returns 和 Action 的函数中使用它,因为它永远不会得到 运行.

你会想写一个 port 在定时器上触发,然后创建一个 Task 来轮询你的 url,然后映射那个 GET 请求的响应到一个动作,调用 actions 邮箱。您可以使用 Task.onError 编写一个简单的错误处理程序,它可以通过在您的 Action 类型上创建一个 Error String 构造函数来将错误消息转发到您的视图。

这是一个例子:

getEmailData _ =
  let
    request =
      Http.get emailJsonDecoder jsonUrl
        |> Task.map AddEmails
  in
    request
      `Task.onError` (\err -> Task.succeed (Error (toString err)))
      `Task.andThen` (\action -> Signal.send actions.address action)

port getEmails : Signal (Task a ())
port getEmails =
  Signal.map getEmailData (Time.every (Time.minute / 6.0) )

以上代码将导致 URL 被检索、解析,然后,如果成功,它将触发您的 actions 邮箱并导致视图更新。如果有错误,它将发送 Error 的新动作和一条消息,您应该在视图中处理该消息。 (您必须将 Error String 添加到 Action 联合类型,并在模型、更新和视图函数中处理它。