PostMessage with multiple functions or custom callbacks

前端 未结 4 992
刺人心
刺人心 2021-02-05 08:17

So far I\'ve only seen tutorials for postmessage where one window sends a single kind of message, and the other window interprets the message in only a single way.

What

4条回答
  •  我在风中等你
    2021-02-05 08:36

    There are a couple of ways to pass a multi-part message on to a postMessage handler. The first (and less "clean" way) is to use a delimiter character, then pass your data through a string.

    Let's say we wanted to pass a user ID, an action, and the users name. The string would look like this:

    54|do_logout|chris

    Within the postMessage handler, the passed data can be split (docs) on the | character, then each segment of the message can be used as needed.

    Another route, instead of manually creating/splitting a string, is to use JSON (docs) to convert an object into a string on one side, and use JSON to convert back to an object in the handler.

    var pass_data = {
        'name':'Chris',
        'id':54,
        'action':'do_logout'
    };
    target_window.postMessage(JSON.stringify(pass_data), "http://www.example.net");
    

    ... then in the handler:

    function (event) {
        var pass_data = JSON.parse(event.data);
    }
    

    Be sure to test, though, as the JSON object is not provided on all user agents, especially older ones. There are many (many, many) third-party libraries out there to shim JSON support, so don't let the lack of complete adoption scare you away - JSON is definitely a safe "moving forward" standard.

    Wouldn't it be nicer if we could just pass that object straightaway? Well, staring in Firefox 6 (source), the data you pass to a postmessage handler may be an object. The object will be serialized, so there are some concerns on that front, but:

    var pass_data = {
        'name':'Chris',
        'id':54,
        'action':'do_logout'
    };
    target_window.postMessage(pass_data, "http://www.example.net");
    

    A little nicer, eh? Unfortunately, current versions of IE will only deal with strings. I was not able to find any discussion on future plans regarding postMessage for IE 10. Further, there is a known bug in IE 8/9 which breaks postMessage for anything other than frames. (source).

    Getting in to a specific aspect of your question - callbacks. Unless you're able to pass the callback by function name, there isn't a way to pass a function; no anonymous functions for you. This is related to the way the data is actually passed on to the handler. In practice, there "is not" support for objects as data, behind the scenes the browser is turning your passed object into a string (serialization).

    All that said, then, you should understand that passing an object is exactly the same as using JSON to stringify an object before passing, only in the former case the browser is doing its own serialization (and subsequent unserialization), whereas with the latter route it is up to you to serialize/unserialize.

    The take-away points here:

    • postMessage still has limited cross-browser support
    • The trend for newer versions of standards-compliant browsers is to allow passage of objects in addition to strings
    • The passed object will be serialized, so no function references allowed
    • The widest support "in the wild" is for string-only data, which means you'll have to stick with strings and "pack" your data as demonstrated above if you want to support a wide variety of user agents
    • Internet Explorer will ruin every plan you ever make (including family holidays)

    Documentation and References

    • window.postMessage: https://developer.mozilla.org/en/DOM/window.postMessage
    • String.split: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/split
    • IE 8/9 HTML5 support notes: http://blogs.msdn.com/b/ieinternals/archive/2009/09/16/bugs-in-ie8-support-for-html5-postmessage-sessionstorage-and-localstorage.aspx
    • JSON.stringify: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/stringify
    • JSON.parse: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/parse

提交回复
热议问题