bri*_*out 24 javascript html5 webkit web-applications web-worker
我正在尝试使用共享工作者来维护Web应用程序的所有窗口/选项卡的列表.因此,使用以下代码:
//lives in shared-worker.js
var connections=[];//this represents the list of all windows/tabs
onconnect=function(e){
connections.push(e.ports[0]);
};
Run Code Online (Sandbox Code Playgroud)
每次创建窗口时,都会与shared-worker.jsworker 建立连接,并且worker将与窗口的连接添加到connections列表中.
当用户关闭窗口时,它与共享工作程序的连接将过期,应从connections变量中删除.但我找不到任何可靠的方法来做到这一点.
查看规范,connections变量的对象似乎没有包含属性/函数来检查连接是否仍然存在.
可能吗?
同样,总体目标是拥有所有窗口/选项卡的列表.
编辑:一种方法是使共享工作者消息窗口并期待回复.如果共享工作者没有收到回复,那么它将认为该窗口已关闭.在我的实验中,这种方法并不可靠; 问题是没有办法判断一个窗口是关闭还是只是花了很长时间才能回复.
Adr*_*ria 13
这与beforeunload一样可靠,但似乎有效(在Firefox和Chrome中测试过).我绝对赞成投票解决方案.
// Tell the SharedWorker we're closing
addEventListener( 'beforeunload', function()
{
port.postMessage( {command:'closing'} );
});
Run Code Online (Sandbox Code Playgroud)
然后处理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;
}
}
Run Code Online (Sandbox Code Playgroud)
小智 10
我整个星期都在处理同样的问题.
问题是MessagePort规范.坏消息是它没有错误处理,也没有标志,方法或事件来确定它是否已被关闭.
好消息是我已经创建了一个可行的解决方案,但它是很多代码.
请记住,即使在支持的浏览器中,活动的处理方式也不同.例如,如果您尝试发送消息或关闭已关闭的端口,Opera将抛出错误.坏消息是您必须使用try-catch来处理错误,好消息是您可以使用该反馈来关闭至少一侧的端口.
Chrome和Safari无声地失败,不会给您任何反馈,也无法终止无效对象.
我的解决方案涉及交付确认或自定义"回调"方法.您使用setTimeout并使用您的命令将其ID传递给SharedWorker,在处理命令之前,它会发回确认以取消超时.该超时通常挂钩到closeConnection()方法.
这需要一种被动的方法,而不是先发制人,最初我玩弄了TCP/IP协议模型但涉及创建更多的功能来处理每个进程.
一些Psuedo-Code作为例子:
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 */ }
}
Run Code Online (Sandbox Code Playgroud)
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
}
Run Code Online (Sandbox Code Playgroud)
我在这里放了一个完整的演示:http: //www.cdelorme.com/SharedWorker/
我是堆栈溢出的新手,所以我不熟悉他们如何处理大型代码帖子,但我的完整解决方案是两个150行文件.
仅使用交付确认并不完美,因此我通过添加其他组件来改进它.
特别是我正在研究这个ChatBox系统,所以我想使用EventSource(SSE),XHR和WebSockets,只有在所谓的SharedWorker对象中支持XHR,如果我想让SharedWorker做所有的服务器,这会产生一个限制通讯.
此外,由于它需要适用于没有SharedWorker支持的浏览器,我将在SharedWorker中创建长期重复处理,这没有多大意义.
因此,如果我实现SharedWorker,它将仅作为打开选项卡的通信通道,并且一个选项卡将是"控制"选项卡.
如果关闭控制选项卡,则SharedWorker将不知道,因此我向SharedWorker添加了一个setInterval,以便每隔几秒向所有打开的端口发送一个空响应请求.这样,Chrome和Safari就可以在没有处理消息时消除已关闭的连接,并允许更改控制选项卡.
但是,这也意味着如果SharedWorker进程终止,那么选项卡必须有一个间隔,以便每隔一段时间使用相同的方法检入SharedWorker,允许它们使用所有固有的每个选项卡的回退方法.其他浏览器使用相同的代码.
因此,正如您可以看到用于传递确认的回调组合,必须从两端使用setTimeout和setInterval来维护连接知识.它可以做到,但它是后方巨大的痛苦.
PortCollection会派上用场,但似乎没有在任何浏览器中实现。
它充当 MessagePort 对象的不透明数组,从而允许对象在不再相关时被垃圾收集,同时仍然允许脚本迭代 MessagePort 对象。
来源; http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#portcollection
编辑; 刚刚出现了 Chrome 的问题;http://crbug.com/263356
| 归档时间: |
|
| 查看次数: |
4439 次 |
| 最近记录: |