父窗口上下文中来自iframe的Websocket连接
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了父窗口上下文中来自iframe的Websocket连接相关的知识,希望对你有一定的参考价值。
我在页面内有一个页面和一个iframe。两者都托管在同一个域中。我完全控制iframe,但没有父页面的控件。
所以我需要从iframe建立一个websocket连接,但是在父窗口的上下文中,当我导航出iframe(到父页面的其他菜单项)时,保持它活着。
(参见图片)就像在A.html中建立连接一样,并在导航到B和C时保持活着状态。
那可能吗?
答案
简短回答:
直接脚本注入父窗口仍然可能是一个更优雅的解决方案。
答案很长:
Websocket只是一种与服务器的连接。一旦你创建它 - 它会一直存在于浏览器的标签中,如果你卸载创建websocket的脚本,它就不会被破坏。
在iframe中创建websockets的两个问题:
- 每次加载相同的iframe内容时,您可能不希望创建新的websocket连接。
- 卸载iframe后 - 所有websocket的事件处理程序都会丢失(如onopen,onclose,onmessage等)。
您可以尝试在主窗口上创建websocket工厂。该工厂的实例将负责:
- 使用iframe提供的数据创建websocket并将其存储在内部集合属性中
- clone提供了websocket事件处理程序,因此即使卸载原始源也可以访问它们。如果事件处理程序很简单,它将正常工作。
函数克隆存在一些已知问题 - 即,如果它们使用iframe脚本中定义的外部闭包 - 那么闭包将会丢失。您可能想要对克隆库进行研究。
main.js(在主index.html中加载):
var socketsCollection = new SocketsCollection();
function SocketsCollection() {
this.collection = {};
this.add = function(key, obj) {
if (this.exists(key)) return;
// clone websocket event handlers
// PS: this is not the best solution to clone a function. Need a better research here
eval("var onopen = " + obj.onopen.toString());
eval("var onclose = " + obj.onclose.toString());
eval("var onmessage = " + obj.onmessage.toString());
// create websocket
var ws = new WebSocket(obj.url);
ws.onopen = function(e) {
onopen(e, key, ws);
};
ws.onclose = function(e) {
onclose(e, key, ws);
}
ws.onmessage = function(e) {
onmessage(e, key, ws);
}
this.collection[key] = {
key: key,
ws: ws
};
// test websocket is alive
var self = this;
var counter = 1;
window.setInterval(function () {
console.log('testing ' + key);
self.collection[key].ws.send('ping # ' + counter + ' websocket ' + key);
counter++;
}, 2000);
}
this.exists = function(key){
return this.collection[key] !== undefined;
}
}
iframed.js:
function foo(window, socketKey) {
if (window.socketsCollection.exists(socketKey)) return;
var newSocketData = {
url: "wss://echo.websocket.org/",
onopen: function(e, key, ws) {
console.log(key + ' is OPEN', ws.readyState)
ws.send('Hello socket ' + key);
},
onclose: function(e, key, ws) {
console.log(key + ' is CLOSED', ws.readyState)
},
onmessage: function (e, key, ws) {
console.log(key + ' response: ', e.data);
}
};
window.socketsCollection.add(socketKey, newSocketData);
}
a.html:
<script src="iframed.js"></script>
<script>
foo.call(window.parent, window.parent, 'A');
</script>
b.html:
<script src="iframed.js"></script>
<script>
foo.call(window.parent, window.parent, 'B');
</script>
以上是关于父窗口上下文中来自iframe的Websocket连接的主要内容,如果未能解决你的问题,请参考以下文章
子窗口访问父页面iframe中的iframe,top打开的子窗口访问父页面中的iframe中的iframe