Introducing Talker.js—HTML5 postMessage made easy!
At Second Street, we are proud to make white-label software that enables our customers to offer promotions and contests as part of their brand. One of the interesting development challenges behind that has been the need to embed our software on our customers' websites.
An <iframe>
can solve quite a few problems on the web, but it introduces a nearly-impenetrable wall of security. The only way through that wall, if your iframe is on a different domain, is via the HTML5 postMessage
API. Unfortunately, postMessage
is messy.
The Problem with postMessage
While it's great to have something to break the security barrier between a frame and the page it's embedded on, postMessage
has its downsides.
- Your event listener gets every message, from every frame. The signal-to-noise ratio is abysmal.
- There is no guarantee that the other side is ready to receive your message yet.
- Only strings can be sent over the wire.
- The concept of a request/response cycle is completely absent.
Our Tiny Solution
We created a library, talker.js, to solve this problem. At under 1kB minified and gzipped, it's perfect for embedding into applications to make communicating over postMessage
a breeze. And since it's released under the open source MIT License, you can start using it today!
Talker.js wraps postMessage
in an easy-to-use API. It handles queueing your messages until it completes a handshake so it knows both sides are ready, it filters out messages that aren't from Talker on the other side, and it is built on JavaScript Promises, so you can send a request and receive a response.
Using Talker.js
The Talker
constructor takes a window
, and an origin (or '*'
to accept messages from any origin).
var talker = new Talker(myFrame.contentWindow, 'http://example.com/');
Sending Messages
Use Talker#send
to send a message to the other side. Messages have a namespace for organization, and can have an object sent for data transfer. The object must be able to pass through JSON.stringify
.
talker.send('myNamespace', { data: 'here' });
Listening for Messages
Talker will call Talker#onMessage
with a Talker.IncomingMessage
. That message has properties for the namespace
and data
it was originally sent with, as well as an id
and a reference to its talker
.
talker.onMessage = function(message) {
console.log(message.namespace, message.data);
console.log(message.id, message.talker);
};
Responding to Messages
Use Talker.IncomingMessage#respond
to respond to a message with an object. This returns a promise via PinkySwear.js that may resolve with a response if one is sent, or may reject with an error.
talker.onMessage = function(message) {
message.respond({ hello: 'there' });
};
talker.send('localStorage', { get: 'username' })
.then(function(message) {
console.log(message.namespace, message.data);
console.log(message.id, message.talker);
}, function(error) {
console.error(error);
})
;
Getting Talker
Talker.js distributions are available via Bower and GitHub. The source is also on GitHub. Talker is available as a global, a named or anonymous AMD package, or a Common JS package.
$ bower install talkerjs --save
If you'd like to contribute, please Fork us on GitHub, or file an issue with any bug reports or feature requests.