具有多个函数或自定义回调的PostMessage

joh*_*ack 19 javascript postmessage cross-domain

到目前为止,我只看过postmessage的教程,其中一个窗口发送一种消息,另一个窗口只以一种方式解释消息.

如果我想在windows之间进行多种不同的交互,那么postmessage可以处理吗?

这是否违背了postmessage应该做的事情?

例如,如果我想能够来回发送自定义回调等,该怎么办?

Chr*_*ker 54

有几种方法可以将多部分消息传递给postMessage处理程序.第一种(而不是"干净"的方式)是使用分隔符,然后通过字符串传递数据.

假设我们想要传递用户ID,操作和用户名.字符串看起来像这样:

54|do_logout|chris

postMessage处理程序中,传递的数据可以是字符上的split(docs)|,然后可以根据需要使用消息的每个段.

另一种方法是使用JSON(docs)将对象转换为字符串,并使用JSON转换回处理程序中的对象,而不是手动创建/拆分字符串.

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

...然后在处理程序中:

function (event) {
    var pass_data = JSON.parse(event.data);
}
Run Code Online (Sandbox Code Playgroud)

但是,请务必进行测试,因为JSON并未在所有用户代理上提供该对象,尤其是旧代理.有很多(很多很多)第三方库可以提供JSON支持,所以不要让缺乏完整的采用吓跑你 - JSON绝对是一个安全的"前进"标准.

如果我们能直接通过那个物体,那会不会更好?好吧,盯着Firefox 6(源代码),传递给postmessage处理程序的数据可能是一个对象.该对象将被序列化,因此在该方面存在一些问题,但是:

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

好一点,嗯?不幸的是,当前版本的IE只会处理字符串.我无法找到有关postMessageIE 10的未来计划的任何讨论.此外,IE 8/9中存在一个已知的错误,postMessage除了帧之外的其他任何内容.(来源).

了解问题的特定方面 - 回调.除非您能够通过函数名称传递回调,否则无法传递函数; 没有匿名功能.这与数据实际传递给处理程序的方式有关.在实践中,"没有"支持对象作为数据,在后台浏览器将传递的对象转换为字符串(序列化).

所有这一切,那么,你应该明白,传递一个对象与stringify在传递之前使用JSON到一个对象完全相同,只是在前一种情况下,浏览器正在进行自己的序列化(以及后续的反序列化),而后者使用它取决于你序列化/反序列化.

这里的外卖点:

  • postMessage仍然有限的跨浏览器支持
  • 新版标准兼容浏览器的趋势是允许除字符串之外的对象通过
  • 传递的对象将被序列化,因此不允许任何函数引用
  • "在野外"最广泛的支持是针对字符串数据,这意味着如果您想支持各种各样的用户代理,您必须坚持使用字符串并"打包"您的数据,如上所示
  • Internet Explorer将破坏您制作的每个计划(包括家庭假期)

文档和参考

  • 很棒的答案!希望我能在家庭假期评价+10 (5认同)
  • 您始终可以在消息的任何一侧执行JSON编码和解码。 (2认同)