javascript基础学习系列四百九十一:跨上下文消息

跨文档消息,有时候也简称为 XDM(cross-document messaging),是一种在不同执行上下文(如不 同工作线程或不同源的页面)间传递信息的能力。例如,www.wrox.com 上的页面想要与包含在内嵌窗 格中的 p2p.wrox.com 上面的页面通信。在 XDM 之前,要以安全方式实现这种通信需要很多工作。XDM 以安全易用的方式规范化了这个功能。
XDM 的核心是 postMessage()方法。除了 XDM,这个方法名还在 HTML5 中很多地方用到过, 但目的都一样,都是把数据传送到另一个位置。
postMessage()方法接收 3 个参数:消息、表示目标接收源的字符串和可选的可传输对象的数组(只 与工作线程相关)。第二个参数对于安全非常重要,其可以限制浏览器交付数据的目标。下面来看一个 例子:

let iframeWindow = document.getElementById("myframe").contentWindow; iframeWindow.postMessage("A secret", "http://www.wrox.com");

最后一行代码尝试向内嵌窗格中发送一条消息,而且指定了源必须是"http://www.wrox.com"。 如果源匹配,那么消息将会交付到内嵌窗格;否则,postMessage()什么也不做。这个限制可以保护 信息不会因地址改变而泄露。如果不想限制接收目标,则可以给 postMessage()的第二个参数传"*", 但不推荐这么做。
接收到 XDM 消息后,window 对象上会触发 message 事件。这个事件是异步触发的,因此从消息 发出到接收到消息(接收窗口触发 message 事件)可能有延迟。传给 onmessage 事件处理程序的 event
注意 跨上下文消息用于窗口之间通信或工作线程之间通信。本节主要介绍使用 postMessage()与其他窗口通信 。关于工作线程之间通信、MessageChannel 和 BroadcastChannel,可以参考。

// 对数据进行一些处理
processMessage(event.data);
// 可选:向来源窗口发送一条消息 event.source.postMessage("Received!", "http://p2p.wrox.com");
} });

大多数情况下,event.source 是某个 window 对象的代理,而非实际的 window 对象。因此不能 通过它访问所有窗口下的信息。最好只使用 postMessage(),这个方法永远存在而且可以调用。 21
XDM 有一些怪异之处。首先,postMessage()的第一个参数的最初实现始终是一个字符串。后来, 第一个参数改为允许任何结构的数据传入,不过并非所有浏览器都实现了这个改变。为此,最好就是只 通过 postMessage()发送字符串。如果需要传递结构化数据,那么最好先对该数据调用 JSON.stringify(),通过 postMessage()传过去之后,再在 onmessage 事件处理程序中调用 JSON.parse()。
在通过内嵌窗格加载不同域时,使用 XDM 是非常方便的。这种方法在混搭(mashup)和社交应用 中非常常用。通过使用 XDM 与内嵌窗格中的网页通信,可以保证包含页面的安全。XDM 也可以用于 同源页面之间通信。

Encoding API 617

对象包含以下 3 方面重要信息。
 data:作为第一个参数传递给 postMessage()的字符串数据。
 origin:发送消息的文档源,例如"http://www.wrox.com"。
 source:发送消息的文档中 window 对象的代理。这个代理对象主要用于在发送上一条消息的
窗口中执行 postMessage()方法。如果发送窗口有相同的源,那么这个对象应该就是 window
对象。
接收消息之后验证发送窗口的源是非常重要的。与 postMessage()的第二个参数可以保证数据不
会意外传给未知页面一样,在 onmessage 事件处理程序中检查发送窗口的源可以保证数据来自正确的 地方。基本的使用方式如下所示:

window.addEventListener("message", (event) => { 18 // 确保来自预期发送者
if (event.origin == "http://www.wrox.com") {

Encoding API 主要用于实现字符串与定型数组之间的转换。规范新增了 4 个用于执行转换的全局类: 25

Encoding API

TextEncoder、TextEncoderStream、TextDecoder 和 TextDecoderStream。 注意 相比于批量(bulk)的编解码,对流(stream)编解码的支持很有限。
Encoding API 提供了两种将字符串转换为定型数组二进制格式的方法:批量编码和流编码。把字符 串转换为定型数组时,编码器始终使用 UTF-8。

1. 批量编码

所谓批量,指的是 JavaScript 引擎会同步编码整个字符串。对于非常长的字符串,可能会花较长时 间。批量编码是通过 TextEncoder 的实例完成的:

const textEncoder = new TextEncoder();

这个实例上有一个 encode()方法,该方法接收一个字符串参数,并以 Uint8Array 格式返回每个 字符的 UTF-8 编码:

const textEncoder = new TextEncoder();
const decodedText = 'foo';
const encodedText = textEncoder.encode(decodedText);
// f 的 UTF-8 编码是 0x66(即十进制 102)
// o 的 UTF-8 编码是 0x6F(即二进制 111) console.log(encodedText); // Uint8Array(3) [102, 111, 111]

编码器是用于处理字符的,有些字符(如表情符号)在最终返回的数组中可能会占多个索引:

const textEncoder = new TextEncoder();
const decodedText = '☺';
const encodedText = textEncoder.encode(decodedText);
// ☺的UTF-8编码是0xF0 0x9F 0x98 0x8A(即十进制240、159、152、138) console.log(encodedText); // Uint8Array(4) [240, 159, 152, 138]

编码器实例还有一个 encodeInto()方法,该方法接收一个字符串和目标 Unit8Array,返回一个 字典,该字典包含 read 和 written 属性,分别表示成功从源字符串读取了多少字符和向目标数组写 入了多少字符。如果定型数组的空间不够,编码就会提前终止,返回的字典会体现这个结果:

const textEncoder = new TextEncoder();
const fooArr = new Uint8Array(3);
const barArr = new Uint8Array(2);
const fooResult = textEncoder.encodeInto('foo', fooArr); const barResult = textEncoder.encodeInto('bar', barArr);
console.log(fooArr); // Uint8Array(3) [102, 111, 111] console.log(fooResult); // { read: 3, written: 3 }
console.log(barArr); // Uint8Array(2) [98, 97] console.log(barResult); // { read: 2, written: 2 }
encode()要求分配一个新的 Unit8Array,encodeInto()则不需要。对于追求性能的应用,这个 差别可能会带来显著不同。
  • 16
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值