问题描述
我正在使用MessageChannel()在页面和iframe之间传递消息.在我的场景中,iframe是通信发起方,包含它的页面接收,转换并响应iframe.
I'm using MessageChannel() to pass messages between a page and iframe. In my scenario, the iframe is the communications initiator and the page containing it receives, transforms and responds back to the iframe.
在实施系统时,我首先获取并保存了对传递给iframe的端口的引用,将其缓存并继续用于以后的每次通信.
As I was implementing the system I at first took and saved a reference to the port passed to the iframe, cached it and continue to use it for each subsequent communication.
iframe:
window.onmessage = (e) => {
console.log("iframe port established");
//using this port for all following communications
parentPort = e.ports[0];
onmessage = establishedConnectionHandler;
}
我正在运行从所有iframe通过parentPort到父级的所有后续通信:
I'm running all subsequent communications from the iframe to the parent through parentPort:
parentPort.postMessage({command, guid, message});
即使文档指出消息通道是一次性通信,这似乎仍然有效,并且使发起通信变得很方便.
even though the docs state that the message channel is a one-shot communication this appears to work and makes initiating communications convenient.
我的问题-这是受支持的功能还是我正在利用未定义的行为?
My question - is this supported functionality or am I exploiting undefined behavior?
编辑-我必须误解了示例的意图 MDN :
Edit - I must have misunderstood the intent of the example MDN:
button.onclick = function(e) {
e.preventDefault();
var channel = new MessageChannel();
otherWindow.postMessage(textInput.value, '*', [channel.port2]);
channel.port1.onmessage = handleMessage;
function handleMessage(e) {
para.innerHTML = e.data;
textInput.value = '';
}
}
在Kaiido的Plunker示例中对此进行了重构.
This is refactored in Kaiido's Plunker example.
推荐答案
即使在github上阅读代码,也不清楚您在做什么.
That's not really clear what you are doing, even reading your code on github...
您似乎在混淆WindowObject.postMessage方法和MessagePort的方法.在协商部分,WindowObject的应仅使用一次.
因此,让我们退后一步来更基本地解释如何理解事物:
You seem to be confusing the WindowObject.postMessage method and the MessagePort's one. WindowObject's one should be used only once, at the negotiation part.
So let's take a step back to explain more basically how things should be understood:
您应该将消息渠道视为 酸奶锅电话® .
You should think of message channels as a Yoghurt-pot Telephone® .
––––– –––––
po(r)t1 |~~~~~~~~~~~~~~~~~~~~~~~| po(r)t2
––––– –––––
- 一个用户必须创建它.
- 然后,他会将其中一个((em)transfer )分配给其他用户.
- 完成此操作后,每个用户只能访问自己的po(r)t.
- 因此,为了能够接收来自其他用户的消息,他们必须将注意力放在自己的po(r)t上(附加事件处理程序).
- 要发送消息,他们会说消息( postMessage )位于他们仍然拥有的唯一听筒中.
- One user has to create it.
- Then he will give (transfer) one of the po(r)ts to the other user.
- Once this is done, each user has only access to its own po(r)t.
- So to be able to receive messages from the other user, they have to put their ear on their own po(r)t (attach an event handler).
- And to send messages, they will say the message (postMessage) inside the only po(r)t they still have, the same they are listening to.
-
生成酸奶壶电话®,也称为MessageChannel.
Generate The Yoghurt-pot telephone® a.k.a MessageChannel.
因此,要添加一些代码行,您应该做的是:
So to add some lines of code, what you should do is:
var yoghurt_phone = new MessageChannel();
保留其中一个,然后将另一个交给其他用户(iframe).为此,我们使用WindowObject. postMessage 方法,与我们用于通过MessagePorts进行通信的方法不同.
Keep one of the po(r)t and give the other one to the other user (iframe). To do this, we use the WindowObject.postMessage method, which is not the same as the one we'll use to communicate through the MessagePorts.
mains_yoghurt_pot = yoghurt_phone.port1;
frame.contentWindow.postMessage( // this is like a physical meeting
'look I made a cool Yoghurt-phone', // some useless message
'*', // show your id?
[yoghurt_phone.port2] // TRANSFER the po(r)t
);
从框架中取出电源并保持紧紧.
From the frame, receive the po(r)t and keep it tight.
window.onmessage = function physicalMeeting(evt) {
if(evt.ports && evt.ports.length) { // only if we have been given a po(r)t
frames_yoghurt_pot = evt.ports[0];
// ...
从现在开始,每个用户都有自己的po(r)t,只有一个po(r)t.因此,在两端,您都需要在各自的po(r)t上设置侦听器.
From now on, each user has its own po(r)t, and only a single po(r)t. So at both ends, you need to setup listeners on their own single po(r)t.
// from main doc
mains_yoghurt_pot.onmessage = frameTalksToMe;
// from iframe doc
frames_yoghurt_pot.onmessage = mainTalksToMe;
然后,当两个用户之一想要告诉另一个用户时,他们将从他们自己的po(r)t 中进行操作.
And then when one of the two users wants to tell something to the other one, they'll do from their own po(r)t.
// from main doc
mains_yoghurt_pot.postMessage('hello frame');
// or from iframe doc
frames_yoghurt_pot.postMessage('hello main');
这篇关于在页面和iframe之间双向使用MessageChannel()处理多个消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!