postMessage API可以用来解决跨域页面通信的问题。因此,当初决定使用postMessage解决书城和阅读器的通信问题。但是在使用过程中,还是有了波折。按照MDN的文档,书城通过window.open打开阅读器,同时通过readerReferer(阅读器页面句柄)发送信息。阅读器则监听message事件,获取数据。
// 代码大致如下
// 书城
const url = 'xxx'
const readerReferer = window.open(url)
readerReferer.postMessage({
dest: 'reader',
name: 'bookName'
}, url)
// 阅读器
window.addEventListener('message', handleMessage)
function handleMessage (e) {
if (e.data.dest === 'reader') {
console.log(e)
}
}
运行时发现,虽然成功打开了阅读器页面(不成功也难~~),但是阅读器页面始终没有接收到postMessage的信息。网上关于这方面的资料也不多。但好歹找到一个靠谱的说法:postMessage只管发送信息,但对方有没有接收到则不管。
原因找到了,阅读器从打开到监听事件是需要时间的,而书城的信息在此之前就发出了。
网上也提供了解决方法:发送方不立即发送信息,而是等待接收方告知可以发送了再发送信息。
// 修改后的大致代码
// 书城
const url = 'xxx'
const readerReferer = window.open(url)
window.addEventListener('message', canISend)
function canISend(e) {
if (e.data.from === 'reader') {
readerReferer.postMessage({
dest: 'reader',
name: 'bookName'
}, url)
}
}
// 阅读器
window.addEventListener('message', handleMessage)
function handleMessage (e) {
if (e.data.dest === 'reader') {
console.log(e)
}
}
window.opener.postMessage({
from: 'reader'
}, '*')