2

根据这个答案及其有用的 Ellie,我现在知道我们如何在 Elm 0.18 中获得当前时间。

我想获取当前时间,然后以 JSON 格式将其发布到我的服务器。我已经有一个使用硬编码时间戳的 POST,但我只是不知道如何获取当前时间,然后将其包含在我正在发布的 JSON 中。

我的猜测是我需要链接几个命令(获取当前时间,对服务器进行 POST)。

[我还阅读了另一个 SO,它显示了如何通过直接调用update函数连续运行一些命令,这听起来是个好主意,但我不确定它是否适合我的情况。]

实验([编辑] 可能比预期的更分散注意力)

为了解决这个问题,我想我会尝试解决一个类似的问题,我可以在 Ellie 中更轻松地设置它。

原始的 Ellie中获取当前时间,更新到模型中,然后视图函数显示它。

我的版本中,我希望这是一个两步的过程,因此已经将模型发展为一个Maybe Float时间和一个String信息。该view函数显示消息字符串和一个按钮——计划是,当按下按钮时,它会告诉运行时“获取当前时间,然后将其复制到消息槽中”。

如果我能解决这个问题,那么我觉得我可以解决我原来的问题。

我的 Ellie 还没有这样做。当您按下按钮时,时间将被获取并放入 中的time插槽model,但我不知道如何告诉运行时“......现在将该时间复制到消息插槽中”。消息到位,PutTimeInMessage但我不知道如何让它在GetCurrentTime消息/命令之后运行。

有什么建议么?

到目前为止,这是我的代码(它可以编译),您可以在 Ellie 中运行它:

module Main exposing (..)

import Html exposing (..)
import Html.Events exposing (..)
import Time exposing (Time)
import Date
import Task


type alias Model =
    { time : Maybe Float
    , message : String
    }


type Msg
    = OnTime Time
    | GetCurrentTime
    | PutTimeInMessage


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        OnTime t ->
            ( { model | time = Just t }, Cmd.none )

        GetCurrentTime ->
            ( model, getTime )

        PutTimeInMessage ->
            case model.time of
                Nothing ->
                    ( model, Cmd.none )

                Just t ->
                    ( { model | message = toString t }, Cmd.none )


view : Model -> Html Msg
view model =
    div []
        [ div []
            [ button [ onClick GetCurrentTime ] [ Html.text "Get now time." ]
            ]
        , model.message |> Html.text
        ]


getTime : Cmd Msg
getTime =
    Time.now
        |> Task.perform OnTime


main =
    Html.program
        { init = ( Model Nothing "Empty message.", Cmd.none )
        , update = update
        , view = view
        , subscriptions = always Sub.none
        }
4

2 回答 2

2

在我看来,当收到消息时,您可以只更新message字段和字段。因此,整个函数将如下所示:timeOnTimeupdate

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        OnTime t ->
            ( { model | time = Just t, message = toString t }, Cmd.none )

        GetCurrentTime ->
            ( model, getTime )

message设置在OnTime行动中,因为GetCurrentTime时间是未知的,只有在执行getTime功能并OnTime收到消息后才知道。

如果您仍想使用单独的操作来放置message,则可以选择以下代码:

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        OnTime t ->
            update PutTimeInMessage { model | time = Just t }

        GetCurrentTime ->
            ( model, getTime )

        PutTimeInMessage ->
            case model.time of
                Nothing ->
                    ( model, Cmd.none )

                Just t ->
                    ( { model | message = toString t }, Cmd.none )

但老实说,最可取的解决方案只是time在视图中以不同的方式显示,因此您不需要该message字段(但可能我看不到全貌):

view : Model -> Html Msg
view model =
    div []
        [ div []
            [ button [ onClick GetCurrentTime ] [ Html.text "Get now time." ]
            ]
        , viewTime model.time
    ]

viewTime : Maybe Float -> Html Msg
viewTime time =
  case time of
    Nothing -> Html.text "Empty message."
    Just t -> Html.text (toString t)
于 2018-08-05T11:45:55.710 回答
1

我遇到了一个SO,它解释了如何使用Task.andThen. 因为我可以看到的类型Time.now是 aTask我想如果我使用Http.toTask.

下面是我想出的解决方案,它在 Ellie 中

module Main exposing (..)

import Html exposing (..)
import Html.Events exposing (..)
import Http
import Json.Decode as JD
import Json.Encode as JE
import Task
import Time


type alias Model =
    { url : String
    }


type Msg
    = PostTimeToServer
    | PostDone (Result Http.Error String)


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        PostTimeToServer ->
            ( model, postTimeToServer model.url )

        PostDone _ ->
            ( model, Cmd.none )


view : Model -> Html Msg
view model =
    div []
        [ div []
            [ button [ onClick PostTimeToServer ] [ Html.text "POST the current time." ]
            ]
        ]


postTimeToServer : String -> Cmd Msg
postTimeToServer url =
    let
        getTime =
            Time.now

        postTime t =
            JD.string
                |> Http.post url (JE.float t |> Http.jsonBody)
                |> Http.toTask

        request =
            getTime                                            <<-- Here is
                |> Task.andThen postTime                       <<-- the key bit.
    in
        Task.attempt PostDone request


main =
    Html.program
        { init = ( Model "url_here", Cmd.none )
        , update = update
        , view = view
        , subscriptions = always Sub.none
        }
于 2018-08-05T20:35:18.087 回答