JavaScript的:如何知道是否与共享工人的连接还活着?([removed] How to kn

2019-08-03 10:26发布

我试图使用一个共享的工作人员来维持一个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变量似乎并没有持有物业/函数来检查连接是否还活着。

可能吗?
再次,总体目标是使所有的窗口/选项卡的列表中。

编辑:一种方法是使职工共享信息的窗口,并期待着答复。 如果共享的工人没有收到回复那就假定窗口被关闭。 在我的实验中这种方法还没有证明是可靠的; 问题是,有没有办法判断一个窗口被关闭或只是花费很长的时间来回答。

Answer 1:

这仅仅是因为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;
    }
}


Answer 2:

所有环绕一周同样的问题,我的工作一直脖子深的文档。

问题是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的,必须从两端用来保持连接的知识。 这是可以做到,但它在后一个巨大的痛苦。



Answer 3:

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?