sessionStorage do navegador. compartilhar entre guias?

151

Tenho alguns valores no meu site que desejo limpar quando o navegador estiver fechado. Eu escolhisessionStorage armazenar esses valores. Quando a guia é fechada, elas são realmente limpas e mantidas se o usuário pressionar f5; Mas se o usuário abrir algum link em uma guia diferente, esses valores não estarão disponíveis.

Como posso compartilhar sessionStoragevalores entre todas as guias do navegador com meu aplicativo?

O caso de uso: coloque um valor em algum armazenamento, mantenha esse valor acessível em todas as guias do navegador e limpe-o se todas as guias estiverem fechadas.

if (!sessionStorage.getItem(key)) {
    sessionStorage.setItem(key, defaultValue)
}
Vladimir Gordienko
fonte
9
É estranho para mim que isso tenha sido fechado como duplicado. Nomeação para reabertura. O outro tópico é sobre "como se comunicar entre várias guias", que soa diferente e também é diferente quando começo a ler esse outro tópico.
KajMagnus 22/02/19
É possível usar cookies? que se comportam assim por padrão? (mas, de fato - para obter e definir ações, eles
exigirão

Respostas:

133

Você pode usar localStorage e seu eventListener de "armazenamento" para transferir dados sessionStorage de uma guia para outra.

Esse código precisaria existir em TODAS as guias. Ele deve ser executado antes dos outros scripts.

// transfers sessionStorage from one tab to another
var sessionStorage_transfer = function(event) {
  if(!event) { event = window.event; } // ie suq
  if(!event.newValue) return;          // do nothing if no value to work with
  if (event.key == 'getSessionStorage') {
    // another tab asked for the sessionStorage -> send it
    localStorage.setItem('sessionStorage', JSON.stringify(sessionStorage));
    // the other tab should now have it, so we're done with it.
    localStorage.removeItem('sessionStorage'); // <- could do short timeout as well.
  } else if (event.key == 'sessionStorage' && !sessionStorage.length) {
    // another tab sent data <- get it
    var data = JSON.parse(event.newValue);
    for (var key in data) {
      sessionStorage.setItem(key, data[key]);
    }
  }
};

// listen for changes to localStorage
if(window.addEventListener) {
  window.addEventListener("storage", sessionStorage_transfer, false);
} else {
  window.attachEvent("onstorage", sessionStorage_transfer);
};


// Ask other tabs for session storage (this is ONLY to trigger event)
if (!sessionStorage.length) {
  localStorage.setItem('getSessionStorage', 'foobar');
  localStorage.removeItem('getSessionStorage', 'foobar');
};

Eu testei isso no chrome, ff, safari, ie 11, ie 10, ie9

Este método "deve funcionar no IE8", mas não pude testá-lo, pois meu IE estava travando toda vez que abria uma guia .... qualquer guia ... em qualquer site. (bom ol IE) PS: você obviamente precisará incluir um calço JSON se também desejar suporte ao IE8. :)

O crédito é referente a este artigo completo: http://blog.guya.net/2015/06/12/sharing-sessionstorage-between-tabs-for-secure-multi-tab-authentication/

nawlbergs
fonte
2
Quão confiável é esta solução? Como é baseado em eventos, há alguma chance de perder um evento?
vivek241
2
Com base nas respostas aqui, criei uma biblioteca sobre localStorage e sessionStorage para simplificar isso. Então agora você chama apenas storageManager.saveSyncedSessionData ('data', 'key'); ou storageManager.savePermanentData ('data', 'key'); etc com base no que você precisa. O código completo está aqui: ebenmonney.com/blog/…
adentum
@ vivek241 A solução funcionou muito bem para mim quando o tamanho do arquivo JS era menor e "o script da solução" fornecido acima é carregado como o primeiro script da página. Quando o meu arquivo JS ficou muito maior, digamos 1000 ou mais linhas, ele parou de funcionar de repente e também removeu meus cookies e dados específicos do localStorage. Não tenho certeza de que se trate de uma solução confiável ou entre navegadores. Portanto, reescreva toda a lógica para resolver o problema apenas com o cookie.
Webblover 18/01/19
4
O evento não seria acionado em todas as guias abertas anteriormente?
precisa saber é o seguinte
3
Parece que BroadcastChannelagora é uma boa ferramenta para fazer isso. developers.google.com/web/updates/2016/09/broadcastchannel
alexbea
71

Usar sessionStoragepara isso não é possível.

Dos documentos MDN

Abrir uma página em uma nova guia ou janela fará com que uma nova sessão seja iniciada.

Isso significa que você não pode compartilhar entre as guias. Para isso, você deve usar localStorage

Henrik Andersson
fonte
8
Ok, entendi, mas como posso limpar o localStorage quando todas as guias do navegador estão fechadas?
Vladimir Gordienko,
Você pode alterar o cookie de documentos para path='/'forçá-lo a limpar quando a janela do navegador estiver fechada. Mas para as abas, não tenho idéia no momento.
Henrik Andersson
ok eu vou cavar mais fundo e deixar você saber se eu encontrei uma solução, vamos pensar por agora o que torna impossível))
Vladimir Gordienko
5
@ Anmol sim, mas eu não posso fornecer nenhum código já, foi há muito tempo. Esta é uma solução feia, mas funciona perfeitamente para mim. A chave é manter o contador tabsOpened no armazenamento local e aumentá-lo no carregamento da página, mas diminuindo no descarregamento da página. Então, quando a página descarrega e tabsOpen == 1 é a última guia e podemos limpar todas as coisas. Havia algumas coisas menores que eu precisava lidar, mas não consigo lembrar exatamente o que. Espero que ajude você!
precisa
1
@VladimirGordienko, e se o evento de descarregamento que excluir os localStoragedados acontecer, porque alguém navega para um domínio diferente, na mesma guia. Parece-me que isso excluirá os localStoragedados incorretamente - a guia não foi fechada e, se a pessoa voltar, voltará a querer os dados novamente, certo. Enfim, é uma abordagem interessante, não acho de que: -)
KajMagnus
9
  1. Você pode simplesmente usar localStoragee lembrar a data em que foi criada session cookie. Quando localStorage"sessão" é mais antigo que o valor do cookie, você pode limpar olocalStorage

    Contras é que alguém ainda pode ler os dados depois que o navegador é fechado, portanto, não é uma boa solução se seus dados são particulares e confidenciais.

  2. Você pode armazenar seus dados localStoragepor alguns segundos e adicionar um ouvinte de storageevento a um evento. Dessa forma, você saberá quando alguma das guias escreveu algo para o localStoragee poderá copiar seu conteúdo para o e sessionStorage, em seguida, basta limpar olocalStorage

Adassko
fonte
0

Minha solução para não ter sessionStorage transferível em guias foi criar um localProfile e extrair essa variável. Se essa variável estiver definida, mas minhas variáveis ​​sessionStorage não forem executadas, reinicialize-as. Quando o usuário efetua logout da janela, destrua essa variável localStorage

yardpenalty.com
fonte
-14

Aqui está uma solução para impedir o corte da sessão entre as guias do navegador para um aplicativo java. Isso funcionará para o IE (JSP / Servlet)

  1. Na sua primeira página JSP, o evento onload chama um servlet (chamada ajex) para configurar um "window.title" e um rastreador de eventos na sessão (apenas uma variável inteira a ser definida como 0 pela primeira vez)
  2. Certifique-se de que nenhuma das outras páginas defina uma janela.
  3. Todas as páginas (incluindo a primeira página) adicionam um script java para verificar o título da janela quando o carregamento da página estiver concluído. se o título não for encontrado, feche a página / guia atual (certifique-se de desfazer a função "window.unload" quando isso ocorrer)
  4. Defina o evento script da página window.onunload java (para todas as páginas) para capturar o evento de atualização da página, se uma página tiver sido atualizada, chame o servlet para redefinir o rastreador de eventos.

1) primeira página JS

BODY onload="javascript:initPageLoad()"

function initPageLoad() {
    var xmlhttp;

    if (window.XMLHttpRequest) {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }

    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {                           var serverResponse = xmlhttp.responseText;
            top.document.title=serverResponse;
        }
    };
                xmlhttp.open("GET", 'data.do', true);
    xmlhttp.send();

}

2) JS comum para todas as páginas

window.onunload = function() {
    var xmlhttp;
    if (window.XMLHttpRequest) {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {             
            var serverResponse = xmlhttp.responseText;              
        }
    };

    xmlhttp.open("GET", 'data.do?reset=true', true);
    xmlhttp.send();
}

var readyStateCheckInterval = setInterval(function() {
if (document.readyState === "complete") {
    init();
    clearInterval(readyStateCheckInterval);
}}, 10);
function init(){ 
  if(document.title==""){   
  window.onunload=function() {};
  window.open('', '_self', ''); window.close();
  }
 }

3) web.xml - mapeamento de servlet

<servlet-mapping>
<servlet-name>myAction</servlet-name>
<url-pattern>/data.do</url-pattern>     
</servlet-mapping>  
<servlet>
<servlet-name>myAction</servlet-name>
<servlet-class>xx.xxx.MyAction</servlet-class>
</servlet>

4) código do servlet

public class MyAction extends HttpServlet {
 public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws IOException {
    Integer sessionCount = (Integer) request.getSession().getAttribute(
            "sessionCount");
    PrintWriter out = response.getWriter();
    Boolean reset = Boolean.valueOf(request.getParameter("reset"));
    if (reset)
        sessionCount = new Integer(0);
    else {
        if (sessionCount == null || sessionCount == 0) {
            out.println("hello Title");
            sessionCount = new Integer(0);
        }
                          sessionCount++;
    }
    request.getSession().setAttribute("sessionCount", sessionCount);
    // Set standard HTTP/1.1 no-cache headers.
    response.setHeader("Cache-Control", "private, no-store, no-cache, must-                      revalidate");
    // Set standard HTTP/1.0 no-cache header.
    response.setHeader("Pragma", "no-cache");
} 
  }
DTB
fonte
3
Esta pergunta é sobre javascript, não tem nada a ver com javascript.
Victoracheco3107
Esta é uma pergunta que é mais sobre sessionStorage e localStorage
RR1112 11/11/19