Hi, is there a way to use Platform.worker (or some alternative) to make a synchronous calls from javascript to Elm and back?
It would be useful for porting our js code if pure elm functions that don’t produce any tasks would be callable from js.
Hi, is there a way to use Platform.worker (or some alternative) to make a synchronous calls from javascript to Elm and back?
It would be useful for porting our js code if pure elm functions that don’t produce any tasks would be callable from js.
I have been looking into this today, and I think I can see how it is done, but I am not sure if it will be synchronous. I wrote “hello world” Platform.worker style:
main : Program String String Never
main =
Platform.worker
{ init = \flags -> ( "Hello " ++ flags, Cmd.none )
, update = \msg model -> ( model, Cmd.none )
, subscriptions = \model -> Sub.none
}
Looking at the generated code, it is structure is as below (I’ve added some whitespace to try and show better how it is structured):
(function(scope)
{
...
function _Platform_export(exports)
{
scope['Elm']
? _Platform_mergeExportsProd(scope['Elm'], exports)
: scope['Elm'] = exports;
}
...
var author$project$Main$main = elm$core$Platform$worker(
{
....
});
_Platform_export({'Main':{'init':author$project$Main$main(elm$json$Json$Decode$string)(0)}});
} (this) );
In summary, an anonymous function is immediately called, and an internal function within that sets the value of Main
in the Elm
scope, this has a field called init
which is the worker. None of the functions you wrote are exposed outside of this big anonymous function that is wrapped around everything.
You can run the worker like this (https://guide.elm-lang.org/interop/flags.html):
var app = Elm.Main.init({
flags: "ondrej"
});
But there does not appear to be a way to get hold of the model
from inside the Elm program?
You set up ports on the worker like this (https://guide.elm-lang.org/interop/ports.html):
In the Elm program:
port sayHello : String -> Cmd msg
main : Program String String Never
main =
Platform.worker
{ init = \flags -> ( "Hello " ++ flags, sayHello <| "Hello " ++ flags)
, update = \msg model -> ( model, Cmd.none )
, subscriptions = \model -> Sub.none
}
In javascript:
function greet(name) {
var greeting;
var app = Elm.Main.init({
flags: name
});
app.ports.subscribe(function(data) {
greeting = data;
});
return greeting;
}
greet('ondrej');
I am not sure though, that the first command returned from init
will be processed synchronously to make this work?
It looks like it doesn’t work with Platform.worker
https://ellie-app.com/3svkC5KgR6na1 but with Browser.element
it does https://ellie-app.com/3svnmFcvNRXa1.
I’m not sure exactly why
This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.