General Problem: It's really easy to send or receive messages to JavaScript via ports. But if you need to make a roundtrip to JavaScript, your life suddenly gets much harder since there is no request/response mechanism.
In other words, you can send to or receive from JavaScript, but you fall into a hole if you need to do both.
Receiving No Receiving
┌───────────────┬──────────────┐
Sending │ ??? | Cmd msg │
├───────────────┼──────────────┘
No Sending │ Sub msg │
└───────────────┘
Specific Use-Cases: My team needs a read-through cache on the client side, in which we check the localStorage cache through ports and make an HTTP request if it's empty. Right now we have two options:
I think this generalizes onto any situation where you need information from the browser after program initialization (excluding packages that already exist like elm-lang/navigation.) That said, I've run into this problem several times but this is the first time where not having something like this has meant we decided not to implement a feature because the solutions were too difficult in Elm.
Background Materials: If you kinda squint at what I'm asking for, it's basically RPC. So there's a bunch of previous material other systems. Things I think are particularly relevant:
There are also XML-RPC, JSON-RPC, and SOAP. They're all good and bad in their own ways, but share a theme of defining data types that the client and server can agree on. I think changing the data types allowable in ports is out of scope for this request, so they're not as relevant.
There's something in common with all these: they are two parties talking over an unreliable network. I think we need to treat JavaScript the same way. Set timeouts and offer clear visibility into what errors look like.
Suggested Approach:
rpc port name : out1 -> out2 -> Task RPCError res
Where out1 through outN follow the same semantics as outgoing ports, and res follows the same semantics as incoming ports.
RPCError takes care of various failure cases on the JS side: Timeout | Exception String | BadReturnValue String.
On the JavaScript side, an RPC port would be registered on an Elm app on the ports object, with a single method. (Let's call it respondWith to avoid bike shedding here, but the name could certainly be better.)
ports.{name}.respondWith behaves like ports.{name}.subscribe when provided a callback. The difference here: we handle exceptional behavior, set a timeout, and only use the last provided callback. The returned value is treated the same way as a call to ports.{name}.send.
Alternatives: I'm actually having trouble coming up with conceptual alternatives to this proposal. I can think of plenty of ways to implement this, but the diagram above pretty clearly shows where the hole is and I'm not sure of another way to view the problem such that alternate solutions become clear.
That said, here are some alternate implementations I considered:
Known Issues:
Justification:
Meta Note: I had a conversation about roughly this proposal with someone at elm-conf. But it was really hectic and I don't remember who! I just remember being really really excited about this idea! Sorry if it's a duplicate of something somewhere else; I can't find any prior work in the various Elm fora.
--
You received this message because you are subscribed to the Google Groups "elm-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-dev+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elm-dev/0B336033-C511-49CA-8403-E00975CB9C30%40brianthicks.com.
For more options, visit https://groups.google.com/d/optout.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-dev+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elm-dev/CAF7GuPEHaR%3DvbrbS8tknev_WvGi3mh5oCCF5rHb43pyLqHi39g%40mail.gmail.com.