如何使用 elm 0.17 创建 worker

How to create worker with elm 0.17

对于elm 0.16,我只是定义了一些端口 (那只是 Signal 的数据)没有主要功能和 使用 Signal.map 来回处理数据。 它仅用于从 nodejs(不是浏览器)调用的数据处理, 所以我不依赖 Html 模块。

现在 elm 0.17 有 CmdSub 而不是 Signal, 我不知道该怎么做...

谁能给我一个最简单的做数据的例子 通过 worker 初始化公开的端口进行处理 榆树 0.17?


这是我使用 Elm 0.16 的最简单示例...

榆树 0.16 代码:

module Main where
import Signal
import String exposing (isEmpty, reverse)

-- input ports
port jsToElm : Signal String

-- output ports
port elmToJs : Signal String
port elmToJs
  = Signal.map String.reverse jsToElm

javascript (es6) 代码:

/** main */
const Elm = loadElm('./index.js') // custom function to eval Elm code
const app = Elm.worker( Elm.Main, { jsToElm: ''})

app.ports.jsToElm.send('test')

app.ports.elmToJs.subscribe(( txt ) => {    
    console.log( txt )
})

upgrade guide 涉及到这一点,但我将在此处总结并引用您的代码:

输入端口:

-- 0.16
port jsToElm : Signal String

-- 0.17
port jsToElm : (String -> msg) -> Sub msg

输出端口:

-- 0.16
port elmToJs : Signal String

-- 0.17
port elmToJs : String -> Cmd msg

new Elm guide 详细解释了如何连接所有这些。

更新

现在有一个包可以让您创建工人。参见 lukewestby/worker

原答案

我能够通过创建一个 Html.App 程序来获得一个工作示例。我找不到任何方法来解决 main 函数的要求,该函数导致程序包含 view 函数,并且 I'm not alone in that confusion.

我这里的例子是基于浏览器的,希望这适合你的基于节点的版本;只是没用过node版而已

Main.elm:

port module Main exposing (..)

import Json.Decode
import Json.Encode
import Html exposing (..)
import Html.App

import String exposing (isEmpty, reverse)

-- input ports
port jsToElm : (String -> msg) -> Sub msg

-- output ports
port elmToJs : String -> Cmd msg

type alias Flags = { jsToElm : String }

main =
  Html.App.programWithFlags
    { init = init
    , view = view
    , update = update
    , subscriptions = subscriptions
    }

type alias Model = { text : String }

init : Flags -> (Model, Cmd Msg)
init flags =
  (Model flags.jsToElm, Cmd.none)

type Msg
  = Reverse String

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    Reverse str ->
      let reversed = reverse str
      in ({ model | text = reversed }, elmToJs reversed)

view : Model -> Html.Html Msg
view model =
  text <| "text is: " ++ model.text

subscriptions : Model -> Sub Msg
subscriptions _ =
  jsToElm Reverse

index.html:

<script type="text/javascript" src="Main.js"></script>
<script type="text/javascript">
var app = Elm.Main.fullscreen({
  jsToElm: 'first'
});

window.setTimeout(function() {
  app.ports.jsToElm.send('test');
}, 1);

app.ports.elmToJs.subscribe(function ( txt ) {    
    console.log( txt )
});
</script>

几个要点:

  1. 如您所见,信号的简单映射已经消失,对于这么小的示例,样板文件要多得多。这个想法是您设置对端口的订阅,然后在 update 函数中发送 Cmd 当您想将信息发送回 Javascript.
  2. 这整个 Cmd/Sub 需要一个 Program,唯一的方法(我能找到)是包括 [Html.App]。我有一种预感,在未来,核心 Router 类型可以用来制作一个 "headless" worker,但现在看来我们仍然需要 Html.App 程序并且必须渲染视图。
  3. 在将 "test" 发送到 javascript 中的端口时,您会注意到 setTimeout 调用。我不确定 为什么 这个拼凑是必要的,但是 others have seen it before as well