我试图使用一个共享的工作人员来维持一个Web应用程序的所有窗口/选项卡的列表。 因此下面的代码用于:
//lives in shared-worker.js
var connections=[];//this represents the list of all windows/tabs
onconnect=function(e){
connections.push(e.ports[0]);
};
每次创建窗口建立与连接shared-worker.js
工人和工人增加了与窗口的连接connections
列表。
当用户关闭一个窗口及其与共享工人连接期满,并且应该从被除去connections
变量。 但我没有找到任何可靠的方法来做到这一点。
纵观规范中的物体connections
变量似乎并没有持有物业/函数来检查连接是否还活着。
可能吗?
再次,总体目标是使所有的窗口/选项卡的列表中。
编辑:一种方法是使职工共享信息的窗口,并期待着答复。 如果共享的工人没有收到回复那就假定窗口被关闭。 在我的实验中这种方法还没有证明是可靠的; 问题是,有没有办法判断一个窗口被关闭或只是花费很长的时间来回答。
这仅仅是因为beforeunload可靠的,但似乎工作(在Firefox和Chrome测试)。 我绝对赞成它在轮询的解决方案。
// Tell the SharedWorker we're closing
addEventListener( 'beforeunload', function()
{
port.postMessage( {command:'closing'} );
});
然后处理在SharedWorker端口对象的清理。
e.ports[0].onmessage = function( e )
{
const port = this,
data = e.data;
switch( data.command )
{
// Tab closed, remove port
case 'closing': myConnections.splice( myConnections.indexOf( port ), 1 );
break;
}
}
所有环绕一周同样的问题,我的工作一直脖子深的文档。
问题是MessagePort规范。 坏消息是它没有任何错误处理,也没有标志,方法或事件,以确定它是否已经被关闭。
好消息是,我已经创建了一个可行的解决方案,但它是一个大量的代码。
请记住,即使是在支持的浏览器的活动不同的方式处理。 例如,如果你试图消息或关闭一个关闭的端口歌剧院将抛出一个错误。 坏消息是,你必须使用一个try-catch来处理错误,好消息是,你可以使用反馈,收在至少一个端的端口。
Chrome和Safari失败默默离开你没有反馈,没有办法来结束无效对象。
我的解决方案包括交付确认或定制的“回调”的方法。 您可以使用setTimeout和传递ID为它的SharedWorker你的命令,处理命令之前发回一个确认取消超时。 即超时一般钩在closeConnection()方法。
这需要的反应性的方法,而不是先发制人,原来我玩弄使用TCP / IP协议模型,但所涉及创造更多的函数来处理各处理。
一些伪代码为例:
客户端/制表符码:
function customClose() {
try {
worker.port.close();
} catch (err) { /* For Opera */ }
}
function send() {
try {
worker.port.postMessage({command: "doSomething", content: "some Data", id: setTimeout(function() { customClose(); ); }, 1000);
} catch (err) { /* For Opera */ }
}
主题/工人代码:
function respond(p, d) {
p.postMessage({ command: "confirmation", id: d.id });
}
function message(e) {// Attached to all ports onmessage
if (e.data.id) respond(this, e.data);
if (e.data.command) e.data.command(p, e.data);// Execute command if it exists passing context and content
}
我已经把一个完整的展示位置: http://www.cdelorme.com/SharedWorker/
我是新来的堆栈溢出,所以我不熟悉,他们是如何处理大量代码的帖子,但我的完整的解决方案是二150线的文件。
刚开始使用发货确认单是不完美的,所以我在通过添加其他组件提高它的工作。
特别是我正在调查这对客舱系统,所以我想用的EventSource(SSE),XHR和WebSockets的,只有XHR是内部SharedWorker支持的对象据说,它创建了一个限制,如果我想有SharedWorker做所有的服务器通讯。
此外,因为它需要为无SharedWorker支持的浏览器,我将创建SharedWorker内长手重复处理不使一个很有意义的工作。
所以,最后,如果我实现SharedWorker这将是作为唯一的打开的选项卡的通信信道,以及一个选项卡中将控制选项卡。
如果控制选项卡关闭,SharedWorker不会知道,所以我加了一个的setInterval到SharedWorker到每隔几秒钟发送一个空响应请求的所有开放端口。 这允许Chrome和Safari消除当没有消息在被处理的封闭连接,并允许所述控制选项卡更改。
然而,这也意味着如果SharedWorker进程死掉的标签必须有一个间隔使用相同的方法,每隔一段时间与SharedWorker检查中,允许他们使用每个标签换themeselves的后退的方式所固有的一切其他浏览器使用相同的代码。
所以,你可以看到发货确认回调的组合,setTimeout和setInterval的,必须从两端用来保持连接的知识。 这是可以做到,但它在后一个巨大的痛苦。
PortCollection
会派上用场,但似乎并没有在任何浏览器中实现。
它作为MessagePort对象的不透明阵列,由此允许被垃圾收集的对象时,他们不再是相关的,同时仍允许脚本来遍历MessagePort对象。
资源; http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#portcollection
编辑; 只是对于惜售Chrome之外的问题; http://crbug.com/263356
文章来源: JavaScript: How to know if a connection with a shared worker is still alive?