Skip to content

bryclee/post-robot

 
 

Repository files navigation

post-robot [:]-\-<

Post-messaging on the client side using a simple server/client pattern.

Use this if you want to communicate between two different windows (or popups, or iframes) using window.postMessage, but you don't like the fire-and-forget nature of window.postMessage (which doesn't tell you if your message got through, if there was an error, and isn't fully supported in even the latest versions of IE for window to window communication).

With this module, you can set up a listener in one window, have it wait for a post message, and then have it reply with data, all while gracefully handling any errors that crop up.

This also allows cross-domain post messages between two different windows (not just popups) in IE9+.

Features

  • Request/response pattern (avoids sending fire-and-forget messages back and forth)
  • Support for promises and async/await
  • Don't worry about serialization, just send javascript objects
  • Send functions across domains and have them called on the original window
  • Handles all of the corner cases for IE9+, which is normally not able to send cross-domain post messages between two different windows, only iframes
  • Handle error cases gracefully
    • The user closed the window you're trying to message
    • The other window doesn't have any listener set up for your message
    • The other window didn't acknowledge your message
    • You didn't get a response from the other window in enough time

Simple listener / sender

postRobot.on('getCart', function(data, callback) {
    return callback({
        foo: 'bar'
    });
});
postRobot.send(window, 'getCart', function(err, data) {
    console.log(data);
});

One-off listener

postRobot.once('init', function(source, data, callback) {
    ...
});

Listen to a specific window

postRobot.on('init', { window: window.parent }, function(source, data, callback) {
    ...
});

Set a timeout for a response

postRobot.send(window, 'getCart', { timeout: 5000 }, function(err, data) {
    console.log(data);
});

Send a message to the direct parent

postRobot.sendToParent(window, 'getCart', function(err, data) {
    console.log(data);
});

Promises

All of the above can be done with promises rather than callbacks

postRobot.on('getCart', function(source, data) {
    return getFoo(data).then(function(bar) {
        return {
            bar: bar
        };
    });
});
postRobot.once('getCart').then(function(data) {
    ...
}).catch(function(err) {
    ...
});
postRobot.send(window, 'getCart').then(function(data) {
    ...
}).catch(function(err) {
    ...
});

Async / Await

postRobot.on('getCart', async function(source, data) {
    return {
        bar: await bar
    };
});
try {
    let data = await postRobot.once('getCart');
} catch (err) {
    ...
}
try {
    let data = await postRobot.send(window, 'getCart');
} catch (err) {
    ...
}

Functions

Post robot lets you send across functions in your data payload, fairly seamlessly.

For example:

// Window 1:

postRobot.on('getFoo', function(source, data) {
    return {
        bar: function() {
            console.log('foobar!');
        }
    };
});

// Window 2:

postRobot.send(myWindow, 'getFoo').then(function(source, data) {
    data.bar();
});

The function data.bar() will be called on the original window. Because this uses post-messaging behind the scenes and is therefore always async, data.bar() will always return a promise, and must be .then'd or awaited.

IE9+

In order to use post-robot in IE9+ between two different windows on different domains (like a parent window and a popup) you will need to set up an invisible bridge in an iframe on your parent page:

+---------------------+
| Parent xx.com       |
|                     |      +--------------+
|  +---------------+  |      | Popup yy.com |
|  | Bridge yy.com |  |      |              |
|  |               |  |      |              |
|  |               |  |      |              |
|  |               |  |      |              |
|  |               |  |      |              |
|  |               |  |      |              |
|  |               |  |      +--------------+
|  +---------------+  |
|                     |
+---------------------+

Supporting IE9+ in your app is pretty simple:

a. Create a bridge path, for example http://yy.com/bridge.html, and include post-robot:

<script src="http://xx.com/js/post-robot.js"></script>

b. In the parent page, xx.com, include the following javascript:

<script>
    postRobot.openBridge('http://yy.com/bridge.html');
</script>

Now Parent xx.com and Popup yy.com can communicate freely using post-robot in IE.

This can even be done in reverse -- for example, Popup yy.com can include Bridge xx.com if that suits your use cases better.

About

Post-messaging on the client side using a simple server/client pattern.

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 99.2%
  • Other 0.8%