Eu estava procurando uma maneira de se comunicar entre várias guias ou janelas em um navegador (no mesmo domínio, não no CORS) sem deixar vestígios. Havia várias soluções:
A primeira é provavelmente a pior solução - você precisa abrir uma janela a partir da janela atual e só pode se comunicar desde que mantenha as janelas abertas. Se você recarregar a página em qualquer uma das janelas, provavelmente perderá a comunicação.
A segunda abordagem, usando o postMessage, provavelmente habilita a comunicação entre origens, mas sofre o mesmo problema da primeira abordagem. Você precisa manter um objeto de janela.
Terceira maneira, usando cookies, armazene alguns dados no navegador, que podem parecer efetivamente enviar uma mensagem para todas as janelas no mesmo domínio, mas o problema é que você nunca pode saber se todas as guias já leem ou não a "mensagem" antes limpando. Você precisa implementar algum tipo de tempo limite para ler o cookie periodicamente. Além disso, você está limitado pelo tamanho máximo do cookie, que é de 4KB.
A quarta solução, usando o localStorage, parecia superar as limitações dos cookies e pode até ser ouvida usando eventos. Como usá-lo é descrito na resposta aceita.
Editar 2018: a resposta aceita ainda funciona, mas há uma solução mais recente para navegadores modernos, para usar o BroadcastChannel. Veja a outra resposta para um exemplo simples que descreve como transmitir facilmente mensagens entre guias usando BroadcastChannel.
fonte
Respostas:
Editar 2018: é melhor usar o BroadcastChannel para esse fim, veja outras respostas abaixo. No entanto, se você ainda preferir usar o armazenamento local para comunicação entre guias, faça o seguinte:
Para ser notificado quando uma guia envia uma mensagem para outras guias, basta vincular o evento 'storage'. Em todas as guias, faça o seguinte:
A função
message_receive
será chamada toda vez que você definir qualquer valor de localStorage em qualquer outra guia. O ouvinte de eventos também contém os dados recentemente configurados para localStorage, portanto, você nem precisa analisar o próprio objeto localStorage. Isso é muito útil, pois você pode redefinir o valor logo após a configuração, para efetivamente limpar qualquer rastreio. Aqui estão as funções para mensagens:Portanto, agora que suas guias se ligam ao evento onstorage e você tem essas duas funções implementadas, você pode simplesmente transmitir uma mensagem para outras guias chamando, por exemplo:
Lembre-se de que o envio exato da mesma mensagem duas vezes será propagado apenas uma vez; portanto, se você precisar repetir mensagens, adicione um identificador exclusivo a elas, como
Lembre-se também de que a guia atual que transmite a mensagem não a recebe de fato, apenas outras guias ou janelas no mesmo domínio.
Você pode perguntar o que acontece se o usuário carregar uma página da Web diferente ou fechar sua guia logo após a chamada setItem () antes do removeItem (). Bem, do meu próprio teste, o navegador coloca a descarga em espera até que toda a função
message_broadcast()
esteja concluída. Eu testei para colocar algum tempo muito longo no ciclo () e ele ainda esperou o ciclo terminar antes de fechar. Se o usuário matar a guia apenas no meio, o navegador não terá tempo suficiente para salvar a mensagem em disco, portanto, essa abordagem me parece uma maneira segura de enviar mensagens sem nenhum vestígio. Comentários bem-vindos.fonte
Existe uma API moderna dedicada para esse fim - Broadcast Channel
É tão fácil quanto:
Provavelmente, além da limpeza da API, é o principal benefício dessa API - nenhuma string de objeto.
Atualmente suportado apenas no Chrome e Firefox, mas você pode encontrar um polyfill que usa o localStorage.
fonte
Para quem procura uma solução não baseada em jQuery, esta é uma versão JavaScript simples da solução fornecida por Thomas M:
fonte
Checkout AcrossTabs - Comunicação fácil entre as guias do navegador de várias origens. Ele usa uma combinação da API postMessage e sessionStorage para tornar a comunicação muito mais fácil e confiável.
Existem abordagens diferentes e cada uma tem suas próprias vantagens e desvantagens. Vamos discutir cada um:
LocalStorage
Prós :
Contras :
Biscoitos
Prós:
Contras:
Os dados são enviados de volta ao servidor para cada solicitação HTTP (HTML, imagens, JavaScript, CSS, etc.) - aumentando a quantidade de tráfego entre cliente e servidor.
Normalmente, o seguinte é permitido:
sessionStorage
Prós:
localStorage
.Contras:
localStorage
, tt funciona na política de mesma origem . Portanto, os dados armazenados somente estarão disponíveis na mesma origem.Postar mensagem
Prós:
Contras:
targetOrigin
verificação de integridade dos dados que estão sendo transmitidos ao ouvinte de mensagens.Uma combinação de PostMessage + SessionStorage
Usando postMessage para se comunicar entre várias guias e ao mesmo tempo usando sessionStorage em todas as guias / janelas recém-abertas para manter os dados sendo transmitidos. Os dados serão mantidos enquanto as guias / janelas permanecerem abertas. Portanto, mesmo que a aba / janela do abridor seja fechada, as abas / janelas abertas terão todos os dados mesmo após a atualização.
Eu escrevi uma biblioteca JavaScript para isso, chamada AcrossTabs, que usa a API postMessage para se comunicar entre guias / janelas de origem cruzada e sessionStorage para manter a identidade das guias / janelas abertas enquanto elas durarem.
fonte
AcrossTabs
, é possível abrir um site diferente em outra guia e obter os dados dele na guia pai? Terei detalhes de autenticação para outro site.Outro método que as pessoas devem considerar usar é Trabalhadores Compartilhados. Eu sei que é um conceito de vanguarda, mas você pode criar uma retransmissão em um trabalhador compartilhado MUITO mais rápido que o armazenamento local e não exige um relacionamento entre a janela pai / filho, desde que você tenha a mesma origem.
Veja minha resposta aqui para alguma discussão que fiz sobre isso.
fonte
Há um pequeno componente de código-fonte aberto para sincronizar / comunicar-se entre guias / janelas da mesma origem (isenção de responsabilidade - eu sou um dos colaboradores!) Com base
localStorage
.https://github.com/jitbit/TabUtils
PS Tomei a liberdade de recomendá-lo aqui, pois a maioria dos componentes "lock / mutex / sync" falha nas conexões do soquete da web quando os eventos acontecem quase simultaneamente
fonte
Eu criei uma biblioteca sysend.js , é muito pequena, você pode verificar o código fonte. A biblioteca não possui dependências externas.
Você pode usá-lo para comunicação entre guias / janelas no mesmo navegador e domínio. A biblioteca usa BroadcastChannel, se suportado, ou evento de armazenamento de localStorage.
API é muito simples:
quando seu navegador suporta BroadcastChannel, ele enviou um objeto literal (mas na verdade é serializado automaticamente pelo navegador) e, se não, é serializado para JSON primeiro e desserializado por outro lado.
A versão recente também possui a API auxiliar para criar proxy para a comunicação entre domínios. (requer um arquivo html único no domínio de destino).
Aqui está uma demonstração .
EDIT :
A nova versão também oferece suporte à comunicação entre domínios , se você incluir um
proxy.html
arquivo especial no domínio de destino e chamar aproxy
função do domínio de origem:(proxy.html é um arquivo html muito simples, que possui apenas uma tag de script na biblioteca).
Se você quiser uma comunicação bidirecional, precisará fazer o mesmo no
target.com
domínio.NOTA : Se você implementar a mesma funcionalidade usando o localStorage, haverá um problema no IE. O evento de armazenamento é enviado para a mesma janela, que acionou o evento e, para outros navegadores, é invocado apenas para outras guias / janelas.
fonte
Criei um módulo que funciona igual ao Broadcastchannel oficial, mas possui fallbacks baseados em armazenamento local, indexeddb e unix-sockets. Isso garante que sempre funcione mesmo com Webworkers ou NodeJS. Veja pubkey: BroadcastChannel
fonte
Eu escrevi um artigo sobre isso no meu blog: http://www.ebenmonney.com/blog/how-to-implement-remember-me-functionality-using-token-based-authentication-and-localstorage-in-a- aplicação web .
Usando uma biblioteca que eu criei,
storageManager
você pode fazer isso da seguinte maneira:Existem outros métodos convenientes para lidar com outros cenários também
fonte
Esta é uma
storage
parte do desenvolvimento da resposta do Tomas M para o Chrome. Devemos adicionar ouvinteCarregar / salvar item no armazenamento para não executar este evento - DEVEMOS acioná-lo manualmente
e agora, todas as guias abertas receberão evento
fonte