Impedir o cache do navegador do resultado da chamada AJAX

262

Parece que se eu carregar conteúdo dinâmico usando $.get(), o resultado será armazenado em cache no navegador.

Adicionar algumas seqüências aleatórias no QueryString parece resolver esse problema (eu uso new Date().toString()), mas isso parece um hack.

Existe alguma outra maneira de conseguir isso? Ou, se a string única for a única maneira de conseguir isso, outras sugestões são new Date()?

Salamander2007
fonte
Você pode usar a notação curta em $.now()vez de fazer uma (nova Data (). GetTime ()) sempre.
Dayson
1
O título da sua pergunta é um pouco enganador. Você pode mudar o nome?
0112
4
Você já pensou em selecionar outra resposta como a aceita?
M4N

Respostas:

241

Eu uso new Date().getTime(), o que evitará colisões, a menos que você tenha várias solicitações acontecendo no mesmo milissegundo:

$.get('/getdata?_=' + new Date().getTime(), function(data) {
    console.log(data); 
});

Edit: Esta resposta tem vários anos. Ainda funciona (portanto, não o apaguei), mas existem maneiras melhores / mais limpas de conseguir isso agora . Minha preferência é por esse método, mas essa resposta também é útil se você deseja desativar o cache para cada solicitação durante a vida útil de uma página.

Mark Bell
fonte
11
Eu vou votar apenas porque é mais fácil deixar o jQuery fazer isso, como na resposta de Peter J. Sua solução funcionará, mas é mais difícil de manter a longo prazo.
Niklas Wulff
11
Que parte disso requer manutenção? Quando comparado ao que o jQuery faz?
Sunny R Gupta
5
Pode ser interessante notar que o new Date().getTime()código é utilizado como este ... var nocache = new Date().getTime(); var path = 'http://hostname.domain.tld/api/somejsonapi/?cache=' + nocache;. Levei alguns minutos para descobrir isso sozinho. Obviamente, ?cachepode haver qualquer expressão que a API não queira.
doubleJ
1
Marque +1 na resposta de Peter J com uma abordagem melhor. Essa resposta não está errada nem é uma resposta ruim. Acredito que o DV seja feito porque o seu está acima do de Peter (conforme aceito). eo OP não aparece no SO desde o início de 2013
Michel Ayres
1
url = url + (-1 === url.indexOf('?') ? '?' : '&') + "__=" + Number(new Date());
514

A seguir, evitaremos que todas as solicitações futuras do AJAX sejam armazenadas em cache, independentemente do método jQuery que você usar ($ .get, $ .ajax, etc.)

$.ajaxSetup({ cache: false });
Peter J
fonte
7
Após a investigação (Fiddler), parece que o jQuery implementa isso internamente, simplesmente acrescentando um carimbo de data / hora de qualquer maneira (conforme discutido em outras partes nestas respostas). Para mim, o método .ajaxSetup é mais limpo (na minha opinião.) #
Peter J
8
Na verdade, ele não precisa estar dentro da chamada de documento pronto.
22411 Peter J
19
Por que desativar o cache de ajax globalmente? Eu acho que isso deve ser feito por chamada, como o que a resposta de Jonathan faz.
Sunny R Gupta
5
O que funcionar para o seu aplicativo. Continuo usando esse método em aplicativos comerciais sempre que preciso absolutamente de dados atualizados para todas as chamadas AJAX. Para outros, os dados em cache são bons.
Peter J
1
link Descrição: Defina valores padrão para solicitações futuras do Ajax. Seu uso não é recomendado.
Itwebdeveloper
319

O $ .get () do JQuery armazenará em cache os resultados. Ao invés de

$.get("myurl", myCallback)

você deve usar $ .ajax, que permitirá desativar o cache:

$.ajax({url: "myurl", success: myCallback, cache: false});
Jonathan Moffatt
fonte
62
+1 Esta é a resposta correta. A solução de Peter J para desabilitar o cache globalmente é uma má prática da IMO.
Salman von Abbas
7
Importante observar que é apenas "global" para a página / solicitação.
9788 Peter
3
+1: o cache deve ser específico ao tipo de solicitação. Algumas solicitações do servidor podem precisar de armazenamento em cache (onde os dados do servidor são estáticos), portanto, escolher o armazenamento em cache em uma solicitação por solicitação é melhor do que simplesmente desativar tudo .
Gone Coding
1
+1 para resposta correta - impedindo o armazenamento em cache por chamada usando o método jQuery, em vez de um hack manual.
Brendan Hill
2
Outra boa resposta. Devo dizer que, na maioria das vezes, a desativação global do cache tem sido de grande benefício. Tudo depende de como seu aplicativo foi projetado. Não há marcador de prata, mas nessa situação, eu recomendaria uma função que aceite um booleano para armazenamento em cache, função para retorno de chamada e URL para modularidade. O manual "hack" está bom, mas se você estiver usando o jQuery, atenha-se às funções deles sempre que possível. Isso não apenas facilitará o desenvolvimento agora, mas também futuras atualizações para a biblioteca.
Anthony Mason
24

Todas as respostas aqui deixam uma pegada no URL solicitado, que aparecerá nos logs de acesso do servidor.

Eu precisava de uma solução baseada em cabeçalho sem efeito colateral e achei que isso pode ser alcançado configurando os cabeçalhos mencionados em Como controlar o cache de páginas da web em todos os navegadores? .

O resultado, trabalhando pelo menos no Chrome, seria:

$.ajax({
   url: url, 
   headers: {
     'Cache-Control': 'no-cache, no-store, must-revalidate', 
     'Pragma': 'no-cache', 
     'Expires': '0'
   }
});

Auxílio em
fonte
Talvez seja uma pergunta estúpida, mas se meu ajax retornar imagens, as imagens serão armazenadas em cache? Para evitar solicitações maciças do Amazon S3?
Marcelo Agimóvel 04/07/19
MarceloAgimóvel, essa pode ser uma pergunta SO separada, acredito.
Aidin
23

outra maneira é não fornecer cabeçalhos de cache do lado do servidor no código que gera a resposta à chamada ajax:

response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );
miceuz
fonte
17
Incorreta. No IE, os cabeçalhos sem cache são ignorados para chamadas XMLHttpRequest, conforme discutido aqui: stackoverflow.com/questions/244918/… O DateTime (ou meu método .ajaxSetup) são as únicas soluções que realmente funcionam.
Peter J
eu só colado meu costume sem cache mantra, não é indicado que é IE específico
miceuz
2
Isso deve interromper o cache de todos os navegadores: response.setHeader ("Cache-Control", "max-age = 0, sem cache, sem armazenamento, pós-verificação = 0, pré-verificação = 0");
precisa saber é o seguinte
13

Pessoalmente, sinto que o método da string de consulta é mais confiável do que tentar definir cabeçalhos no servidor - não há garantia de que um proxy ou navegador não apenas o armazene em cache de qualquer maneira (alguns navegadores são piores que outros - sem nome).

Geralmente uso, Math.random()mas não vejo nada de errado em usar a data (você não deve fazer solicitações AJAX com rapidez suficiente para obter o mesmo valor duas vezes).

Greg
fonte
2
Combine Date (). GetTime () junto com Math.random () e você deverá estar do lado seguro. Além disso, o Ext.Ajax também usa getTime () quando disableCaching é especificado.
vividos 15/12/08
12

Seguindo a documentação: http://api.jquery.com/jquery.ajax/

você pode usar a cachepropriedade com:

$.ajax({
    method: "GET",
    url: "/Home/AddProduct?",
    data: { param1: value1, param2: value2},
    cache: false,
    success: function (result) {
        // TODO
    }
});
MrMins
fonte
5

É claro que as técnicas de "quebra de cache" farão o trabalho, mas isso não aconteceria em primeiro lugar se o servidor indicasse ao cliente que a resposta não deveria ser armazenada em cache. Em alguns casos, é benéfico armazenar em cache as respostas, outras vezes não. Deixe o servidor decidir o tempo de vida correto dos dados. Você pode alterá-lo mais tarde. Muito mais fácil de fazer no servidor do que em muitos lugares diferentes no seu código de interface do usuário.

Claro que isso não ajuda se você não tiver controle sobre o servidor.

Mark Renouf
fonte
5

Que tal usar uma solicitação POST em vez de uma GET ...? (O que você deveria mesmo assim ...)

Thomas Hansen
fonte
Eu acho que é uma solução melhor, mas infelizmente eu (de alguma forma) só posso fazer solicitação GET. Então .. é novo Date (). GetTime () por enquanto.
Salamander2007
Por favor, adicione alguma explicação à sua resposta para que outras pessoas possam aprender com ela - por que uma solicitação POST é necessária?
Nico Haase
5

A verdadeira questão é por que você precisa que isso não seja armazenado em cache. Se não deve ser armazenado em cache porque muda o tempo todo, o servidor deve especificar para não armazenar em cache o recurso. Se apenas mudar algumas vezes (porque um dos recursos dos quais depende pode mudar) e se o código do cliente tiver uma maneira de saber sobre ele, ele poderá anexar um parâmetro fictício ao URL que é calculado a partir de algum hash ou data da última modificação desses recursos (é o que fazemos nos recursos de script do Microsoft Ajax para que eles possam ser armazenados em cache para sempre, mas novas versões ainda podem ser exibidas conforme aparecem). Se o cliente não puder conhecer as alterações, a maneira correta deve ser para o servidor manipular solicitações HEAD corretamente e informar ao cliente se deve usar a versão em cache ou não. Parece-me que acrescentar um parâmetro aleatório ou dizer ao cliente para nunca armazenar em cache está errado porque a cache é uma propriedade do recurso do servidor e, portanto, deve ser decidido no lado do servidor. Outra pergunta a ser feita é se esse recurso realmente deve ser servido através do GET ou deve passar pelo POST? Essa é uma questão de semântica, mas também tem implicações de segurança (existem ataques que funcionam apenas se o servidor permitir o GET). O POST não será armazenado em cache.


fonte
6
E se você estiver passando por servidores proxy que não controla a política de cache? e se o seu aplicativo precisar fazer explicitamente uma nova solicitação sempre? A resposta para as coisas nem sempre é clara em preto e branco, sempre há áreas cinzentas.
7wp 31/03
É verdade que nem sempre é claro. Mas ver essa resposta me fez questionar minhas suposições e me levou a encontrar a causa raiz do meu problema. Pode não ser o caso para todos, mas me ajudou. Se você está aqui lendo isso, considere também.
Jonathan Tran
Isso me ajudou, o ResponseCaching foi definido como servidor de 60m por padrão. Alterou para No-Cache e parou de armazenar em cache no cliente.
mattygee 17/03
4

Talvez você devesse olhar para $ .ajax () (se você estiver usando jQuery, com o que ele se parece). Dê uma olhada em: http://docs.jquery.com/Ajax/jQuery.ajax#options e a opção "cache".

Outra abordagem seria examinar como você armazena em cache as coisas no lado do servidor.

finpingvin
fonte
1
Infelizmente, após alguma investigação, usar $ .ajax () e definir cache = false basicamente fará a mesma coisa. O jQuery adicionará algum número aleatório à string de consulta e não verifica a string de consulta existente. Então, acho que usar $ .get () será suficiente.
precisa
Ah, ok. Nunca tentei, me lembrei que eu tinha visto algo sobre isso nos docs :)
finpingvin
Nem é necessário usar $ .ajax. Basta usar .ajaxSetup.
Peter J
3

Uma pequena adição às excelentes respostas fornecidas: se você estiver executando uma solução de backup não-ajax para usuários sem javascript, terá que corrigir os cabeçalhos do lado do servidor de qualquer maneira. Isso não é impossível, embora eu entenda aqueles que desistem;)

Tenho certeza de que há outra pergunta no SO que fornecerá o conjunto completo de cabeçalhos apropriados. Não estou inteiramente convencido de que a resposta do mouse abrange todas as bases 100%.

krosenvold
fonte
3

Para aqueles que usam a cacheopção do $.ajaxSetup()Safari móvel, parece que você precisará usar um carimbo de data / hora para POSTs, pois o Safari móvel também armazena em cache. De acordo com a documentação em $.ajax()(da qual você é direcionado $.ajaxSetup()):

Definir cache como false funcionará corretamente apenas com solicitações HEAD e GET. Ele funciona anexando "_ = {timestamp}" aos parâmetros GET. O parâmetro não é necessário para outros tipos de solicitações, exceto no IE8, quando um POST é feito para uma URL que já foi solicitada por um GET.

Portanto, definir essa opção por si só não o ajudará no caso mencionado acima.

Athasach
fonte
2

Basicamente, basta adicionar cache:false;no ajax, onde você acha que o conteúdo mudará à medida que o progresso avança. E o lugar onde o conteúdo não muda lá você pode omitir isso. Desta forma, você receberá a nova resposta sempre

Santosh Upadhayay
fonte
2

Cache do Ajax do Internet Explorer: O que você fará sobre isso? sugere três abordagens:

  1. Adicione um token de bloqueio de cache à string de consulta, como? Date = [timestamp]. No jQuery e no YUI, você pode solicitar que eles façam isso automaticamente.
  2. Use POST em vez de um GET
  3. Envie um cabeçalho de resposta HTTP que proíbe especificamente navegadores para armazená-lo em cache
LCJ
fonte
2

Agora, é fácil fazer isso ativando / desativando a opção de cache em sua solicitação ajax, assim

$(function () {
    var url = 'your url goes here';
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
                cache: true, //cache enabled, false to reverse
                complete: doSomething
            });
        });
    });
    //ToDo after ajax call finishes
    function doSomething(data) {
        console.log(data);
    }
});
Omar El Don
fonte
3
Depois de 6 anos, você está dando a mesma resposta que Jonathan? ಠ_ಠ
redent84
as pessoas podem dizer que são 6 anos após a publicação da pergunta. E minha resposta a essa pergunta é diferente de qualquer outra, sem mencionar que é a correta hoje em dia. Responder a essas perguntas não é para o "solicitante", é para a comunidade e iniciantes! Obrigado por adicionar o esclarecimento de qualquer maneira!
Omar El Don
E qual é a diferença entre a sua e esta stackoverflow.com/a/735084/469218 ?
redent84
talvez seja clareza, do ponto de vista de um iniciante que faz essa pergunta !!
Omar El Don
1

Como o @Athasach disse, de acordo com os documentos do jQuery, $.ajaxSetup({cache:false})não funcionará além de solicitações GET e HEAD.

É melhor você enviar de volta um Cache-Control: no-cachecabeçalho do seu servidor de qualquer maneira. Ele fornece uma separação mais limpa das preocupações.

Obviamente, isso não funcionaria para os URLs de serviço que você não pertence ao seu projeto. Nesse caso, considere fazer proxy do serviço de terceiros do código do servidor, em vez de chamá-lo do código do cliente.

rstackhouse
fonte
1

Se você estiver usando o .net ASP MVC, desative o armazenamento em cache na ação do controlador adicionando o seguinte atributo à função de ponto final:

[OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
Marius
fonte
Você pode explicar isso mais? Como essa matriz se relaciona com o AJAX?
Nico Haase
Não é uma matriz, é um atributo em uma ação do controlador MVC.
Marius
0

adicionar cabeçalho

headers: {
                'Cache-Control':'no-cache'
            }
Moaz Salem
fonte
Por favor, adicione alguma explicação à sua resposta para que outras pessoas possam aprender com ela - onde esses cabeçalhos devem ser adicionados?
Nico Haase
-3

anexar Math.random() ao URL da solicitação

xiaoyifang
fonte
2
Isso dará resultados instáveis.
precisa saber é
Math.random funcionará apenas como um parâmetro, como url? _ = [Math.Random ()], não tem nada a ver com resultado instável.
precisa saber é o seguinte
4
Eu entendo o que você estava fazendo. Eu estava apenas comentando que Math.Random () às vezes fornece o mesmo número duas vezes. Se você preencher seu sistema com incertezas, elas serão adicionadas apenas umas sobre as outras.
precisa saber é o seguinte