Fork me on GitHub

JSChannel Documentation

Verifying the correctness of the code on this page...

All the code on this page is correct.

Some code on this page doesn't work.



Introduction

JSChannel is a small JavaScript abstraction layer on top of HTML5 cross-document messaging. It builds rich messaging semantics out of window.postMessage().

About The Code Examples

This page uses the doctestjs library by Ian Bicking. The code examples are actually run on your browser to verify their correctness.

All the code examples in this documentation assume communication between a parent page and a child frame. Example code executed in the child frame looks like this:

The examples also assume that a few global functions exist in the parent page:

Page Setup

JSChannel has no dependencies, so there's very little setup involved. You can get started by making a simple HTML page that includes the JSChannel script:
<script src="jschannel.js"></script>
And a trivial child frame:
<iframe id="childId" src="child.html"></iframe>

The contents of the child frame don't matter, so long as it includes the JSChannel script (so that it can communicate with its parent).

Note that we're just using a child frame for the sake of example; as a rule, JSChannel can be used anywhere that window.postMessage() can.

Creating a Channel

Let's create a channel in our child frame:

And now we'll build one in our parent page to communicate with it:

Note that the onReady callback is called once actual communication has been established between the parent page and child frame. If the child frame hadn't set up its end of the channel, for instance, onReady would never get called.

If you pass a bogus first parameter to Channel.build(), a friendly exception is thrown. The origin parameter is used for security purposes, just as in window.postMessage(), and it can take many different forms: ...except for obvious exceptions. And the scope parameter can include almost any characters to automatically namespace the channel so it doesn't conflict with other channels: But a channel's scope can't include double colons.

Remote Methods

Now we'll define a simple function in our child frame:

And call it in our parent frame.

Of course, more than just strings can be returned from a remote call. Assume we have a trivial echo function like this:

It's possible for a remote method to return any native JavaScript types, like numbers:

null works, too:

As do booleans:

Remote methods can throw errors, too. Here's one in our child frame:

Calling that produces this:

But objects with keys other than error and message...

...get smushed into strings by attempting to serialize them to JSON.

But objects that can't be serialized to JSON just get coerced to strings:

You can throw arrays, too:

And strings...

Totally unintentional exceptions get propagated, too:

Transactions

If your method's implementation is asychronous, you'll have to use the transaction object that's automatically passed as the first argument to a remote method, like so:

The caller doesn't do anything differently, since it's always calling the remote method asynchronously:

You can use a transaction's error() method to propagate errors, too.

Callbacks

Clients can pass functions as parameters to remote methods, and they can be called by the implementer. Here's a trivial example:

Callback parameters can be nested, too, and they arrive in the order in which they were originally called:

Timeouts

Clients can also be notified if a remote method invocation takes too long to complete by passing a timeout parameter to a channel's call() method.

For instance, we can try calling a nonexistent method with a timeout:

Of course, the timeout doesn't get triggered if the method call actually completes...

Notifications

Notifications are similar to method calls, but are "fire-and-forget", lacking any concept of an error or return value. For example: