UPDATE: There is now native support for this here.
Over the past few weeks i have been working with Platform Events in a number of my Lightning projects, such as the Custom Metadata Services and Event Logging. This component allows you to receive Platform Events in your own components.
This component can be deployed from this repository here. I have been working on this for a while and I have yet to highlight this component on my blog. I wanted to rectify that now and I also wanted to take some time to explain lessons learned along the way and if anyone else has any thoughts on improving it even further!
Using the Component
Firstly using the component is very easy, you just need two attributes as you can see above. The channel defines the event and the onMessage attribute the handler for the event. I learnt along the way that if you define a registerEvent in your component it automatically exposes an attribute that takes a callback handler, much nicer for users of your component! The payload event parameter contains the platform event fields.
Wrapping CometD in a Component World
The component uses the CometD JavaScript library internally. This library does require a certain amount of configuration and authentication tweaks to initialise (such as disabling WebSockets, since LEX does not currently support it). Also, as i found out eventually, code to unsubscribe from events is also needed.
In the Visualforce page examples this was less of a concern in a page centric world. In the world of components this becomes very important! Without it, i was finding that when i navigated around Lightning Experience and back to components using this component i would accumulate handlers, that would effectively appear to be repeating events, not good.
In order to find the correct moment to unsubscribe and disconnect, the component listens to the aura:valueDestroy event. This does not fire immediately however, so some additional defensive work in the internal handler is needed. I am certainly open to further comments on how to make this component more robust.
This Trialhead module also includes example code on how to use the CometD library in Lightning, though the result is not a generic component like the one in this blog. I am also less sure about its design in terms of unsubscribing only on page unload.
Summary
Access to creating, sending and receiving Platform Events are available in Apex, REST API’s, Process Builder and Flow. Hopefully one day we will see a platform provided Lightning Base Component to replace the one i have created here. Meanwhile have fun!
November 15, 2017 at 7:23 pm
Slick library, glad you made it and shared it with folks!
We use the same cometD library in our Lightning Components when we want to stream Platform Events.
A word to the wise: there was a change in recent versions of that library that Lockerservice does NOT like. I believe it’s 2.9.3 and later (you’re using 2.9.1 it seems).
Here’s the commit that makes LockerService blow up. You can safely revert this commit in your own version of the library if you choose to use a later version number than 2.9.1.
https://github.com/cometd/cometd/commit/f2ce6e490d5d6be06387ce2e29969aa1fdf8e041
Banged my head on the wall on this one for a good half day a while back.
November 16, 2017 at 8:38 pm
Thanks for sharing! Appreciated! How did you do then unsubscribe btw?
November 17, 2017 at 2:26 pm
We don’t have the same unsubscribe challenges you had to deal with building your library, as we have a singleton component at the top level that listens for PlatformEvents (and re-emits them as Application events in Lightning). Individual components that get built and destroyed (and may be interested in these Application Events) don’t affect the Platform Event subscription.
The singleton is always live if the application is open.
November 19, 2017 at 8:18 am
Ok makes sense, though if your users navigate around to and from your page, handlers may still build up I think.
November 22, 2017 at 11:37 am
For backwards-compatibility with Classic we’re running all our Lightning Components with Lightning Out on a Visualforce page. So the Lightning Experience tab you click on to see the app is an iframe. I believe, but might be wrong, that all the state from the iframe is discarded when the frame is destroyed.
November 22, 2017 at 12:44 pm
That would be my expectation, of course when folks start using your component in containers more advanced than Lightning out, you may have to revisit.
February 7, 2018 at 4:07 pm
Hi Andy,
did you get any issue of type “Exception during handling of messages Unrecognized advice action handshake” in your implementation ?
February 12, 2018 at 6:59 pm
I did during early days. I made improvements to How cometd is configured since. Check not only the one in this repo but the one in the standalone streaming component repo under my user. I trie to keep them in sync.
February 21, 2018 at 4:02 am
is this the standalone repo u mean:
https://github.com/afawcett/streamingcomponent
March 20, 2018 at 2:00 am
Hi Andrew! I tried to use your component from https://github.com/afawcett/streamingcomponent
but I am getting an error
10:54:04.836 Exception during handling of messages Unrecognized advice action handshake
You wrote that you have fixed it, so probably I am using a wrong repo? coud you provide a link, please?
Thank you!
March 20, 2018 at 4:52 pm
It looks like there could be a bug in the platform from what I have been hearing. The workarounds is to switch off Lightning notifications
March 21, 2018 at 2:02 am
Thank you, Andrew! Switching off notifications made the issue go away, but we need notifications, so hoping SF will fix it soon.
Pingback: User Notifications with Utility Bar API | Andy in the Cloud
April 16, 2018 at 5:12 pm
Andrew, SFDC has imposed very strict limits on # of PE delivered to cometd clients. Do those limits include Lightning component subscriptions (since this too uses cometd)? I hope not. I’m migrating from Streaming to PEs to get around the limits on Streaming events since I am not sure I can purchase additional blocks of, like we can for PEs.
April 16, 2018 at 5:34 pm
I honestly do not know on this. It’s best to talk to your Salesforce account rep.
Pingback: How to refresh record details in Lightning when you change them in APEX - Blog Martina Humpolce
July 13, 2018 at 9:24 am
Hey Andrew — this component is great. I’m using it in a component, which is then embedded in a Flow. That Flow is exposed in a Community.
It is running great when launched just in the Flow, but in the community, getting a status error at streaming.js:40.
Any thoughts on why this would not work in a Community?
Thanks!
July 22, 2018 at 8:09 am
It could be that the community user does not have the api permission not sure…. what specific error are you seeing?
December 3, 2018 at 10:09 am
Hi, how to you about Replay -2, to retrieve the last saved events?
December 15, 2018 at 12:20 pm
You can now use this Salesforce component that also supports -2 https://developer.salesforce.com/docs/component-library/bundle/lightning:empApi/documentation