连接端口和订阅时遇到问题
Trouble Connecting Ports and Subscriptions
我正在通读 Elm guide 和他们的 JavaScript interOp。这是一个简化版本:
port module FooBar exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.App as Html
import String
main =
Html.program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- subscriptions
port f : () -> Cmd msg
port g : ( Int -> msg ) -> Sub msg
subscriptions: Model -> Sub Msg
subscriptions model = g Get
-- MODEL
type alias Model = { pt : Int }
-- VIEW
view: Model -> Html Msg
view model = Html.text ( toString model.pt )
-- UPDATE
type Msg = Ask | Get Int
update: Msg -> Model -> (Model, Cmd msg)
update msg model =
case msg of
Ask -> (model, f () )
Get x -> ( Model x, Cmd.none )
-- INIT
init: (Model, Cmd Msg)
init = ( Model 0, f ())
应用程序初始设置为 0 但它应该从 JavaScript 读取消息并设置为 1。但是,它仍保持在 0。 Elm 端口是否设置正确?
<div id="foobar"></div>
<script src="foo.js"></script>
<script>
var node = document.getElementById("foobar");
var app = Elm.FooBar.embed(node);
app.ports.f.subscribe(
function(){
var myValue = 1;
console.log(myValue);
app.ports.g.send(myValue);
}
);
</script>
</body>
这里我放:elm-make foo.elm --output=foo.js
myValue
以 1 形式打印到控制台的事实表明 f()
端口被调用,但 g()
端口从未被发送返回或处理得当。
很难判断这是否是设计决定,但 init
在 Html.App
订阅任何端口之前被调用。
因此从 init
调用 f ()
将无效。
我使用 send
函数,它运行一个虚拟任务并始终发送 Ask
消息,这将触发传出端口。
考虑更改您的 init
以发送消息,将数据发送到端口:
-- INIT
init : ( Model, Cmd Msg )
init =
-- ( Model 0, f ())
( Model 0, send Ask )
send : msg -> Cmd msg
send msg =
Task.perform identity identity (Task.succeed msg)
如果您只是想将默认值从 Javascript 发送到您的 Elm 应用程序,您可以使用 programWithFlags,无需尝试连接到尚未设置的端口向上:
main =
Html.programWithFlags
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- INIT
type alias Flags = { initialValue : Int }
init : Flags -> (Model, Cmd Msg)
init flags = ( Model flags.initialValue, Cmd.none )
这允许您像这样通过 Javascript 发送初始值:
var app = Elm.FooBar.embed(node, { initialValue : 2 });
我正在通读 Elm guide 和他们的 JavaScript interOp。这是一个简化版本:
port module FooBar exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.App as Html
import String
main =
Html.program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- subscriptions
port f : () -> Cmd msg
port g : ( Int -> msg ) -> Sub msg
subscriptions: Model -> Sub Msg
subscriptions model = g Get
-- MODEL
type alias Model = { pt : Int }
-- VIEW
view: Model -> Html Msg
view model = Html.text ( toString model.pt )
-- UPDATE
type Msg = Ask | Get Int
update: Msg -> Model -> (Model, Cmd msg)
update msg model =
case msg of
Ask -> (model, f () )
Get x -> ( Model x, Cmd.none )
-- INIT
init: (Model, Cmd Msg)
init = ( Model 0, f ())
应用程序初始设置为 0 但它应该从 JavaScript 读取消息并设置为 1。但是,它仍保持在 0。 Elm 端口是否设置正确?
<div id="foobar"></div>
<script src="foo.js"></script>
<script>
var node = document.getElementById("foobar");
var app = Elm.FooBar.embed(node);
app.ports.f.subscribe(
function(){
var myValue = 1;
console.log(myValue);
app.ports.g.send(myValue);
}
);
</script>
</body>
这里我放:elm-make foo.elm --output=foo.js
myValue
以 1 形式打印到控制台的事实表明 f()
端口被调用,但 g()
端口从未被发送返回或处理得当。
很难判断这是否是设计决定,但 init
在 Html.App
订阅任何端口之前被调用。
因此从 init
调用 f ()
将无效。
我使用 send
函数,它运行一个虚拟任务并始终发送 Ask
消息,这将触发传出端口。
考虑更改您的 init
以发送消息,将数据发送到端口:
-- INIT
init : ( Model, Cmd Msg )
init =
-- ( Model 0, f ())
( Model 0, send Ask )
send : msg -> Cmd msg
send msg =
Task.perform identity identity (Task.succeed msg)
如果您只是想将默认值从 Javascript 发送到您的 Elm 应用程序,您可以使用 programWithFlags,无需尝试连接到尚未设置的端口向上:
main =
Html.programWithFlags
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- INIT
type alias Flags = { initialValue : Int }
init : Flags -> (Model, Cmd Msg)
init flags = ( Model flags.initialValue, Cmd.none )
这允许您像这样通过 Javascript 发送初始值:
var app = Elm.FooBar.embed(node, { initialValue : 2 });