Repository navigation
Allow messages to be sent to apps - #259
Conversation
Codecov Report
@@ Coverage Diff @@
## master #259 +/- ##
=====================================
Coverage 100% 100%
=====================================
Files 3 3
Lines 145 146 +1
Branches 44 44
=====================================
+ Hits 145 146 +1
Continue to review full report at Codecov.
|
|
There are lots of situations you may find yourself in, where you may want your hyperapp-app to be it's own, self-contained thing, within a larger system of logic. Where moving all the rest of the logic into your hyperapp app is not feasible or desirable. In such situations, want your app to be able to receive messages from the "outside" -- but you don't want to be dependent on what the outside is (because it might be changing). So you want to set up a "consumer-agnostic" interface for your app. The great thing is: we don't need to add any new concepts! The This PR makes |
|
Some situations where this would be useful:
|
|
@zaceno Thanks! I'll wait until we've figured out components, since I am still not sure about how to implement those exactly. |
|
@jbucaran No problem. Can't truly focus on more than one thing at a time :) But just to be clear: This PR doesn't overlap or have anything to with components. Components are about what goes on 'inside' an app. This is about letting the app be aware of stuff going on outside it. |
|
http://tech.noredink.com/post/126978281075/walkthrough-introducing-elm-to-a-js-web-app Note the use of ports/signals - that's what I'm going for with this. |
|
This is GREAT! Exactly what I envisioned for cross app communication when sharing a common hyperapp bundle! 🎉 This is also great for socket.io or other things (many of which you mentioned) |
|
I'm a little bummed we have to wait for components before this. That Components thread is on 🔥 ...still... |
| return element | ||
| } | ||
|
|
||
| return emit |
There was a problem hiding this comment.
@zaceno Can you put that return statement before all the functions?
There was a problem hiding this comment.
|
@zaceno If we return the emit function then we close the door to returning the element. Do you think we could regret that in the future? |
|
We could return an object |
|
@lukejacksonn Right. I shouldn't have said "close the door". There's always a way, but it won't be as elegant as having a single return value. 😏 I am tempted to merge this now, but I'd like to hear more about what other people think? /cc @jamen @selfup @SkaterDad @lukejacksonn @matejmazur @traducer |
|
The yo olde elegant vs extensible seesaw. We choose either OR We choose either |
|
Good point about element. Both emit and element are probably useful/necessary in integration scenarios. The difference though, is that you can always find out element somehow. Like a top-level But the Perhaps there are other aspects to integration that I haven't thought about, but I feel pretty confident that So for now, I say we go with just returning |
|
@zaceno Could add some explanation in core.md? Or do you think that's not necessary now? |
|
I really like this change. This makes custom events even more useful and makes any outside service or apps communicating with a |
|
@zaceno How would this look in practice? |
|
@jbucaran sure I'll add some more explanation in the docs. as for "how this would look in practice"... well, lets go with the "I'm porting my app written in framework X to hyperapp"-scenario. Like at work we have this app made with Backbone/Marionette. It's big and complicated so if we were going to port it, we'd do it one bit at a time. Lets say we go for the mediaplayer part of it. We're just converting our media-player with it's controls, to hyperapp. So the app would need ways to signal out to the rest of the application things like: "user pressed pause" "current timestamp is ..." "I need more media to keep playing". Those are examples of outgoing messages. The app can be told how to send those, by defining callbacks in the events/actions of the app. And the app would have to be able to take in messages like "here's your new media", "jump to this timestamp", and some other syncronization signals (we have multiple player windows that need to play back in sync, even though their media may come in at slightly different times) These are incoming signals. The "inner" mediaplayer app defines events for these (like And then the outer backbone app can : |
We let the `app(...)` call return its emit-function. This allows external agents to send messages to the app, and the app doesn't need to know who they are and how they communicate. It only needs to define its external interface in the `events` property.
|
ebf3087 adds "integration" section to |
|
I really like this idea. 👍 Once this is landed, you could get more Returning an object would certainly be the most flexible solution long-term. I'm not sure I see the use case for returning the element, though? |
|
@SkaterDad For integrating a third party with hyperapp, I think the best route is not using an emitter, but wrapping the library into a functional component (custom tags) and use the lifecycle events. |
|
@jbucaran but featherjs (after just now learning about them and checking their website) seems like a backend-communication library. Nothing to render. So seems to me that events are the way to hook in (wether external or internal) -- not lifecycle methods |
|
@SkaterDad Nah you're probably right. I had a PR before where the app would return the element, because I was trying to make app's work like stateful components, and I needed the element to inject it into the tree of the parent app. But again, you can always find the element anyway, so I closed that PR. I think just returning EDIT: typo |
|
@zaceno What if instead of returning emit, we return render()? |
|
@jbucaran I don't think render() is enough. Like in my example of porting a part of a Backbone/Marionette app. There are different types of messages you want the app to recieve, and you want to be able to pass it a payload (like "here's new media for you to play") Essentially, you want to be able to affect the state of the app, while leaving it up to the app to define what ways and how state is managed and represented. |
|
What if we return a function that works like this: var zap = app({ ... })
zap((emit, render) => {
// Want to render?
render(/* different view */)
// Want to emit?
emit("msg", data)
}) |
|
As long as we expose emit somehow, I'm happy :) I don't really see the point in your ...sure it's more work than what you're suggesting. But I don't see that asking an app to render itself would be a common use case either. Maybe that thing you had in your example: " |
|
@zaceno Awesome thanks! Last question, how would you actually use this? A module that runs hyperapp / calls app() and export the emit function? export const emit = app({ state, view, actions }) |
|
Could be in a module, sure. In the example I brought up about porting an app that seems sensible. But I can also imagine it as a way to start bringing some sanity into a web app made up of just jquery-spaghetti. In that case you wouldn't have modules and a build-system (probably) So it depends I guess. |
|
@jbucaran I'm calling it now — it will manage to break something for me. I don't know how, yet. 🙂 |
|
@dodekeract Unlikely, app never returned anything. Now, #275 might break stuff. 😏:wink: |
|
🎉 Thanks, everyone involved! @dodekeract from now on, if anything breaks, just assume it's my fault, ok? ;) |
|
OMG it is in! This is amazing, now I can easily use hyperapp for a side project (web sockets hehe) I had in mind 👍 🎉 Thank you so much @zaceno 🥇 |
We let the `app(...)` call return its emit-function. This allows external agents to send messages to the app, and the app doesn't need to know who they are and how they communicate. It only needs to define its external interface in the `events` property. 🐵🙈

We let the
app(...)call return its emit-function. This allowsexternal agents to send messages to the app, and the app doesn't
need to know who they are and how they communicate. It only needs
to define its external interface in the
eventsproperty.