Os Web Workers compartilhados persistem em uma única recarga de página, navegação de link
-
27-10-2019 - |
Pergunta
Trabalhadores da Web compartilhados são projetados para permitir várias páginas deo mesmo site (origem) para compartilhar um único Web Worker.
No entanto, não está claro para mim a partir das especificações (ou outros tutoriais e informações sobre trabalhadores compartilhados) se o trabalhador compartilhado persistirá se você tiver apenas uma janela / guia do site e navegar para outra página no mesmo site.
Isso seria mais útil no caso de uma conexão WebSocket do trabalhador compartilhado que permanece conectado enquanto o site é navegado.Por exemplo, imagine um ticker da bolsa ou área de bate-papo que persistiria (sem a necessidade de reconectar o WebSocket) mesmo enquanto o site fosse navegado.
Solução
Fiz alguns testes para descobrir a resposta para isso na prática.
O Firefox ainda não oferece suporte à criação de conexões WebSocket de Web Workers: https:// bugzilla. mozilla.org/show_bug.cgi?id=504553 Portanto, o Firefox não é relevante até que o bug seja resolvido.
O IE 10 não tem suporte para Web Workers compartilhados , portanto, também não é relevante. Resta o Chrome.
Aqui está um exemplo para testar web workers compartilhados.
Primeiro o HTML:
<!DOCTYPE html>
<html>
<body>
<a href="shared.html">reload page</a>
<script>
var worker = new SharedWorker("shared.js");
worker.port.addEventListener("message", function(e) {
console.log("Got message: " + e.data);
}, false);
worker.port.start();
worker.port.postMessage("start");
</script>
</body>
</html>
Em seguida, a implementação do próprio trabalhador compartilhado em shared.js
:
var connections = 0;
self.addEventListener("connect", function(e) {
var port = e.ports[0];
connections ++;
port.addEventListener("message", function(e) {
if (e.data === "start") {
var ws = new WebSocket("ws://localhost:6080");
port.postMessage("started connection: " + connections);
}
}, false);
port.start();
}, false);
Resultados do teste no Chrome 20 ( a resposta ):
Quando a página é carregada simultaneamente em duas guias separadas, a contagem de conexões aumenta cada vez que uma das páginas é recarregada ou o link autorreferencial é clicado.
Se apenas uma única instância da página for carregada, a contagem de conexões nunca será alterada quando a página for recarregada ou o link for clicado.
Portanto, no Chrome 20: Web Workers compartilhados não persistem em recarregamentos de página e cliques de navegação em link .
Outras dicas
Parece que este é basicamente o mesmo problema que a questão 'O que acontece com um thread de trabalho da web HTML5 quando a guia é fechada durante a execução?' . Acho que a parte principal da especificação é esta declaração :
Os agentes do usuário podem invocar o modelo de processamento "matar um trabalhador" em um trabalhador a qualquer momento, por exemplo, em resposta às solicitações do usuário, em resposta a Gerenciamento de cota de CPU ou quando um trabalhador deixa de ser um ativo necessário trabalhador se o trabalhador continuar executando mesmo após seu sinalizador de fechamento foi definido como verdadeiro.
Um ' ativo trabalhador necessário 'é definido da seguinte forma:
Um trabalhador é considerado um trabalhador ativo necessário se qualquer um dos documentos os objetos nos Documentos do trabalhador estão totalmente ativos.
Portanto, pelo que entendi, se todas as janelas que fazem referência a um trabalhador forem fechadas, o navegador é obrigado pela especificação a encerrar o trabalhador, mas não imediatamente. Dependendo dele, a persistência não será confiável, mesmo que pareça funcionar ocasionalmente.
Em seu exemplo, minha abordagem seria carregar todo o site por Ajax - você não conseguirá executar os Web Workers se seus usuários desativaram o JS de qualquer maneira, então use o API de histórico para fazer com que o endereço da página do usuário corresponda a a página real (mantendo o mecanismo de pesquisa e a compatibilidade não JS).
Tive sucesso com uma técnica meio indireta em que, quando quero ir para a próxima página, mas mantenho o SharedWorker, abro uma janela pop-up (esperançosamente discreta) que cria o mesmo trabalhador, espero que ele se torne ativo eenvia uma mensagem para a porta / janela original, que então navega para a nova página e, quando a página é carregada, fecha o pop-up.Essa estratégia mantém pelo menos uma conexão ativa o tempo todo, para que o trabalhador nunca decida desligar.
Esta técnica parece ser bastante robusta até agora.Embora ver o pop-up seja um tanto chato, é um meio-termo razoável para alguns casos de uso.