Apakah Safari di iOS 6 memberikan hasil caching $ .ajax?

1072

Sejak peningkatan ke iOS 6, kami melihat tampilan web Safari mengambil kebebasan dari $.ajaxpanggilan caching . Ini dalam konteks aplikasi PhoneGap sehingga menggunakan Safari WebView. $.ajaxPanggilan kami adalahPOST metode dan cache disetel ke false {cache:false}, tetapi ini masih terjadi. Kami mencoba menambahkan secara manual TimeStampke header tetapi tidak membantu.

Kami melakukan lebih banyak riset dan menemukan bahwa Safari hanya mengembalikan hasil cache untuk layanan web yang memiliki fungsi tanda tangan yang statis dan tidak berubah dari panggilan ke panggilan. Misalnya, bayangkan fungsi yang disebut sesuatu seperti:

getNewRecordID(intRecordType)

Fungsi ini menerima parameter input yang sama berulang-ulang, tetapi data yang dikembalikan harus berbeda setiap waktu.

Harus terburu-buru Apple untuk membuat iOS 6 zip bersama mengesankan mereka terlalu senang dengan pengaturan cache. Adakah orang lain yang melihat perilaku ini di iOS 6? Jika demikian, apa sebenarnya penyebabnya?


Solusi yang kami temukan adalah mengubah tanda tangan fungsi menjadi sesuatu seperti ini:

getNewRecordID(intRecordType, strTimestamp)

dan kemudian selalu mengirimkan TimeStampparameter juga, dan hanya membuang nilai itu di sisi server. Ini mengatasi masalah ini. Saya harap ini membantu beberapa jiwa miskin lainnya yang menghabiskan 15 jam pada masalah ini seperti yang saya lakukan!

pengguna1684978
sumber
190
Ini benar-benar mengejutkan. Kami juga baru saja menghabiskan beberapa jam mencoba mencari tahu sesuatu yang baru saja berhenti bekerja. Login AJAX kami yang melakukan POST (dan memiliki tajuk untuk mencegah caching juga) sedang di-cache oleh Safari sehingga hanya mengembalikan JSON yang sama seperti yang dilakukan terakhir kali tanpa mencoba server ... tidak dapat dipercaya! Kita harus meretas perbaikan, tetapi jangan pernah men-cache POST, itu gila.
Kieran
16
Posting solusi Anda sebagai jawaban daripada pembaruan untuk pertanyaan itu.
ChrisF
50
Permintaan POST bersifat non-idempoten, yang berarti permintaan tersebut tidak boleh di-cache kecuali respons secara khusus menyarankan hal itu melalui header responsnya.
James M. Greene
6
Untuk membuat Apple memperbaiki ini, ajukan bug di bugreport.apple.com . Saya sudah melakukan hal yang sama.
Mathias Bynens
11
Mark Nottingham (ketua kelompok kerja IETF HTTPbis) menulis posting blog yang menarik tentang hal ini hari ini: mnot.net/blog/2012/09/24/caching_POST
Benjamin Brizzi

Jawaban:

447

Setelah sedikit penyelidikan, ternyata Safari di iOS6 akan men-cache POST yang tidak memiliki header Kontrol-Cache atau bahkan "Kontrol-cache: max-age = 0".

Satu-satunya cara yang saya temukan untuk mencegah caching ini terjadi di tingkat global daripada harus meretas querystrings acak ke akhir panggilan layanan adalah dengan mengatur "Kontrol Cache: no-cache".

Begitu:

  • Tidak ada Cache-Control atau Expires header = iOS6 Safari akan melakukan cache
  • Cache-Control max-age = 0 dan Expired = iOS6 Safari akan cache
  • Kontrol Cache: no-cache = iOS6 Safari TIDAK akan melakukan cache

Saya menduga bahwa Apple mengambil keuntungan dari ini dari spec HTTP di bagian 9.5 tentang POST:

Respons terhadap metode ini tidak dapat di-cache, kecuali jika responsnya menyertakan bidang Cache-Control atau Expire header yang sesuai. Namun, respons 303 (Lihat Lainnya) dapat digunakan untuk mengarahkan agen pengguna untuk mengambil sumber daya yang dapat di-cache.

Jadi secara teori Anda bisa menyimpan respons POST ... yang tahu. Tetapi tidak ada pembuat browser lain yang pernah berpikir itu akan menjadi ide yang bagus sampai sekarang. Tapi itu TIDAK menjelaskan caching ketika tidak ada header Kontrol-Cache atau Kedaluwarsa yang ditetapkan, hanya ketika ada beberapa set. Jadi itu pasti bug.

Di bawah ini adalah apa yang saya gunakan di bagian kanan konfigurasi Apache saya untuk menargetkan seluruh API saya karena ketika itu terjadi saya tidak benar-benar ingin melakukan cache apa pun, bahkan dapat. Apa yang saya tidak tahu adalah bagaimana mengatur ini hanya untuk POST.

Header set Cache-Control "no-cache"

Pembaruan: Hanya perhatikan bahwa saya tidak menunjukkan bahwa itu hanya ketika POST sama, jadi ubah data atau URL POST mana saja dan Anda baik-baik saja. Jadi Anda bisa seperti yang disebutkan di tempat lain hanya menambahkan beberapa data acak ke URL atau sedikit data POST.

Pembaruan: Anda dapat membatasi "tanpa cache" hanya untuk POST jika Anda ingin seperti ini di Apache:

SetEnvIf Request_Method "POST" IS_POST
Header set Cache-Control "no-cache" env=IS_POST
Kieran
sumber
7
Saya melihat ke mana Apple akan melakukan ini, tetapi kami melihat respons Cached terhadap permintaan POST bahkan ketika respons kami tidak menyertakan header Kontrol-Cache atau Kedaluwarsa. Apakah ini contohnya iOS6 tidak boleh cache dan mengirim setiap permintaan. Ini tidak terjadi.
Kango_V
138
Bagian dari spesifikasi HTTP yang Anda kutip tidak membenarkan perilaku caching iOS 6. Perilaku default adalah untuk tidak menembolok tanggapan POST (yaitu ketika tajuk "Kontrol-Cache" tidak ditentukan). Perilaku tersebut melanggar spesifikasi dan harus dianggap sebagai bug. Siapa pun yang membangun layanan web xml / json api harus menghiasi respons POST mereka dengan "Cache-control: no-cache" untuk mengatasi masalah ini.
David H
39
Permintaan POST bersifat non-idempoten, yang berarti permintaan tersebut tidak boleh di-cache kecuali respons secara khusus menyarankan hal itu melalui header responsnya.
James M. Greene
4
Seperti yang dikatakan David, ini jelas merupakan pelanggaran terhadap kalimat yang Anda kutip. Jika tidak ada "Cache-Control atau Kedaluwarsa bidang header", header yang sesuai jelas tidak termasuk. Namun investigasi Anda sendiri menunjukkan cache dalam skenario itu. Harap edit jawaban Anda.
Matthew Flaschen
3
Adakah yang tahu berapa lama hasilnya di-cache di perangkat? Saya telah mencoba membunuh safari dan memulai kembali ponsel saya, tetapi masih di-cache. Saya tahu ini bekerja dengan menghapus cache browser tapi saya bertanya-tanya berapa lama untuk pengguna yang pernah memiliki masalah sebelum hilang. Tidak semua orang akan berpikir untuk membersihkan cache mereka ...
Daniel Hallqvist
146

Saya harap ini bisa berguna untuk pengembang lain membenturkan kepala mereka ke dinding yang satu ini. Saya menemukan bahwa salah satu dari berikut ini mencegah Safari di iOS 6 dari caching respons POST:

  • menambahkan [cache-control: no-cache] di header permintaan
  • menambahkan parameter URL variabel seperti waktu saat ini
  • menambahkan [pragma: no-cache] di header respons
  • menambahkan [cache-control: no-cache] di header respons

Solusi saya adalah sebagai berikut dalam Javascript saya (semua permintaan AJAX saya adalah POST).

$.ajaxSetup({
    type: 'POST',
    headers: { "cache-control": "no-cache" }
});

Saya juga menambahkan header [pragma: no-cache] ke banyak respons server saya.

Jika Anda menggunakan solusi di atas, ketahuilah bahwa setiap panggilan $ .ajax () yang Anda buat diatur ke global: false TIDAK akan menggunakan pengaturan yang ditentukan dalam $ .ajaxSetup (), jadi Anda perlu menambahkan header lagi.

Dave
sumber
4
Ini adalah solusi THE CORRECT untuk bug. Bugnya adalah bahwa iOS 6 akan melayani permintaan POST dari cache itu alih-alih mengirimkannya ke server. Bugnya bukan karena cache respons dari permintaan POST (yang diizinkan). Jika Anda masih ingin tanggapan terhadap permintaan POST diambil dari cache untuk permintaan GET berikutnya untuk URI itu, gunakan solusi ini.
Nicholas Shanks
2
Ini bekerja untuk saya, tetapi saya tidak mengerti caranya. Saya sudah menentukan cache: false di ajaxSetup saya, dan melihat header permintaan, yang bermuara pada Kontrol-Cache: no-cache dan Pragma: no-cache - tetapi itu masih akan cache di iPad. Lalu ketika saya menambahkan header: {"cache-control": "no-cache"} ke ajaxSetup, itu menggandakan header Cache-Control menjadi "no-cache, no-cache" - dan menghentikan caching. Apa yang sedang terjadi disini?
Tom W Hall
Berfungsi sempurna - Anda juga dapat menambahkan ke permintaan sebagai parameter $ .ajax ({type: 'POST', tajuk: {'cache-control': 'no-cache'}, dll.))
George Filippakos
Apa itu [pragma: no-cache]? Untuk apa kunci pragma digunakan?
zakdances
Saya juga berpikir ini adalah pendekatan terbaik, daripada solusi dengan parameter tambahan. Kami telah menambahkan ini hanya pada panggilan di mana kami membutuhkannya, untuk panggilan yang selalu memiliki pengembalian yang sama, caching mungkin merupakan hal yang baik untuk pengguna akhir.
germankiwi
67

Solusi sederhana untuk semua permintaan layanan web Anda, dengan asumsi Anda menggunakan jQuery:

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    // you can use originalOptions.type || options.type to restrict specific type of requests
    options.data = jQuery.param($.extend(originalOptions.data||{}, { 
      timeStamp: new Date().getTime()
    }));
});

Baca lebih lanjut tentang panggilan prefilter jQuery di sini .

Jika Anda tidak menggunakan jQuery, periksa dokumen untuk perpustakaan pilihan Anda. Mereka mungkin memiliki fungsi serupa.

Baz1nga
sumber
3
Tidak berfungsi bagi saya, server merespons: "JSON primitif tidak valid: timeStamp" asp.net / iis 7.5
Alexandre
3
bagaimana dengan $ .ajax ({"cache": false ...})? apakah ini akan berfungsi saat menambahkan _ = [TIMESTAMP]? (Saya tidak memiliki alat semacam itu untuk mengujinya)
Karussell
Saya telah memposting implementasi penuh dari solusi yang diusulkan oleh Karussell. Lihat jawaban saya di bawah ini.
Sam Shiles
1
@ Karussell. Baru saja mencoba mengatur $ .ajax ({"cache": false ...}). Ini tidak menyelesaikan masalah untuk permintaan POST di iOS6. Mungkin karena JQuery sesuai dokumen mereka menganggap tidak ada browser yang cukup bodoh untuk men-cache permintaan posting. "Halaman yang diambil dengan POST tidak pernah di-cache, sehingga opsi cache dan ifModified di jQuery.ajaxSetup () tidak berpengaruh pada permintaan ini."
Brett Hannah
1
Ini tidak berhasil. Itu tidak menggabungkan parameter posting. Posting oleh Dave adalah solusi yang lebih baik.
Chris Muench
43

Saya baru saja mengalami masalah ini juga dalam aplikasi PhoneGap . Saya menyelesaikannya dengan menggunakan fungsi JavaScript getTime()dengan cara berikut:

var currentTime = new Date();
var n = currentTime.getTime();
postUrl = "http://www.example.com/test.php?nocache="+n;
$.post(postUrl, callbackFunction);

Saya menghabiskan beberapa jam untuk mencari tahu ini. Akan menyenangkan jika Apple memberi tahu pengembang tentang masalah caching ini.

Bashevis
sumber
1
Saya akan mengomentari penggunaan {cache:false}sebagai opsi untuk salah satu $.post()atau $.ajaxSetup(), tetapi menurut dokumen , argumen ini diabaikan; jQuery akan 'tidak pernah cache' permintaan posting, tetapi tidak mempertimbangkan browser. Mungkin opsi yang lebih rapi adalah menambahkan timestamp ke permintaan yang menggunakan $.ajaxPrefilter().
fwielstra
saya menghabiskan hampir 5 jam untuk memperbaiki masalah ini, dan akhirnya menambahkan cap waktu akan melakukan trik function send_ajax(my_data,refresh) .. lihat di sini stackoverflow.com/questions/14733772/…
rusly
42

Saya memiliki masalah yang sama dengan aplikasi webapp mendapatkan data dari layanan web ASP.NET

Ini bekerja untuk saya:

public WebService()
{
    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    ...
}
Tadej
sumber
2
Terima kasih banyak! Saya menjadi gila mencoba mencari tahu mengapa iPhone bertindak begitu berbeda dari setiap platform lainnya. Solusi spesifik ASP.NET ini menghemat waktu saya.
Mark Brittingham
Tidak berfungsi untuk iOS6 melihat jawaban saya menjelang akhir utas
Brian Ogden
1
Silahkan!!!! Syarat untuk menerapkan ini hanya pada iOS 6, cache konten sangat penting untuk aplikasi apa pun.
Alexandre
24

Akhirnya, saya punya solusi untuk masalah unggahan saya.

Dalam JavaScript:

var xhr = new XMLHttpRequest();
xhr.open("post", 'uploader.php', true);
xhr.setRequestHeader("pragma", "no-cache");

Dalam PHP :

header('cache-control: no-cache');
goker.cebeci
sumber
15

Dari posting blog saya sendiri, iOS 6.0 caching permintaan Ajax POST :

Cara memperbaikinya: Ada berbagai metode untuk mencegah caching permintaan. Metode yang disarankan adalah menambahkan header no-cache. Ini adalah bagaimana hal itu dilakukan.

jQuery:

Periksa iOS 6.0 dan tetapkan tajuk Ajax seperti ini:

$.ajaxSetup({ cache: false });

ZeptoJS:

Periksa iOS 6.0 dan atur tajuk Ajax seperti ini:

$.ajax({
    type: 'POST',
    headers : { "cache-control": "no-cache" },
    url : ,
    data:,
    dataType : 'json',
    success : function(responseText) {…}

Sisi server

Jawa:

httpResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");

Pastikan untuk menambahkan ini di bagian atas halaman sebelum data dikirim ke klien.

.BERSIH

Response.Cache.SetNoStore();

Atau

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);

PHP

header('Cache-Control: no-cache, no-store, must-revalidate'); // HTTP 1.1.
header('Pragma: no-cache'); // HTTP 1.0.
kiranvj
sumber
2
Atribut tanpa cache yang bagus untuk .NET stackoverflow.com/questions/10011780/…
Aran Mulholland
7

Cuplikan JavaScript ini bekerja sangat baik dengan jQuery dan jQuery Mobile:

$.ajaxSetup({
    cache: false,
    headers: {
        'Cache-Control': 'no-cache'
    }
});

Cukup letakkan di suatu tempat dalam kode JavaScript Anda (setelah jQuery dimuat, dan terbaik sebelum Anda melakukan permintaan AJAX) dan itu akan membantu.

Jonathan
sumber
6

Anda juga dapat memperbaiki masalah ini dengan memodifikasi fungsi jQuery Ajax dengan melakukan hal berikut (pada 1.7.1) ke bagian atas fungsi Ajax (fungsi dimulai pada baris 7212). Perubahan ini akan mengaktifkan fitur anti-cache bawaan dari jQuery untuk semua permintaan POST.

(Script lengkap tersedia di http://dl.dropbox.com/u/58016866/jquery-1.7.1.js .)

Masukkan di bawah garis 7221:

if (options.type === "POST") {
    options.cache = false;
}

Kemudian modifikasi berikut ini (mulai dari baris ~ 7497).

if (!s.hasContent) {
    // If data is available, append data to URL
    if (s.data) {
        s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
        // #9682: remove data so that it's not used in an eventual retry
        delete s.data;
    }

    // Get ifModifiedKey before adding the anti-cache parameter
    ifModifiedKey = s.url;

    // Add anti-cache in URL if needed
    if (s.cache === false) {
        var ts = jQuery.now(),
        // Try replacing _= if it is there
        ret = s.url.replace(rts, "$1_=" + ts);

        // If nothing was replaced, add timestamp to the end.
        s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
    }
}

Untuk:

// More options handling for requests with no content
if (!s.hasContent) {
    // If data is available, append data to URL
    if (s.data) {
        s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
        // #9682: remove data so that it's not used in an eventual retry
        delete s.data;
    }

    // Get ifModifiedKey before adding the anti-cache parameter
    ifModifiedKey = s.url;
}

// Add anti-cache in URL if needed
if (s.cache === false) {
    var ts = jQuery.now(),
    // Try replacing _= if it is there
    ret = s.url.replace(rts, "$1_=" + ts);

    // If nothing was replaced, add timestamp to the end.
    s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
}
Sam Shiles
sumber
4
Ini bukan pendekatan yang baik untuk mengubah jQuery atau dalam hal apapun kode yang Anda tidak miliki. (Setiap kali Anda ingin memperbarui versi Anda harus membuat perubahan lagi. (Atau pembaruan pengembang lain dan program tidak bekerja))
andlrc
Ini adalah pendekatan yang benar-benar valid jika Anda perlu solusi tercepat untuk mengurangi kebodohan Apple. Solusi ini telah digunakan untuk menyelesaikan masalah untuk situs besar yang menerima jutaan klik sehari dan memungkinkan kami melakukannya hanya dengan membuat perubahan pada satu file.
Sam Shiles
Anda dapat melihatnya jQuery.ajaxPrefilermemungkinkan Anda memodifikasi permintaan ajax Anda tepat sebelum membuatnya. Anda dapat mengarsipkan hal yang sama dengan yang lebih dioptimalkan dan memperbarui kode aman.
andlrc
1
Masalah dengan pendekatan preFilter adalah Anda harus mendaftarkan filter. Jika Anda memiliki skrip umum yang berjalan ketika setiap halaman dimuat, maka boleh, tetapi jika tidak, Anda harus mengatur preFilter untuk setiap halaman yang menggunakan ajax. Skenario yang saya hadapi, kami memiliki lokasi umum untuk file JQ yang digunakan sebagai sumber daya untuk 7+ situs web individu. Kami kehilangan ribuan pound per jam karena bug ini dan pendekatan yang saya sarankan memungkinkan kami untuk menyelesaikannya dalam waktu sesingkat mungkin dengan mengubah SATU file. Saya setuju dengan Anda pada prinsipnya tetapi Anda terkadang harus pragmatis!
Sam Shiles
Anda kemudian dapat menambahkannya lagi ke akhir file itu. Baik Anda menyelesaikannya, perusahaan Anda pasti senang untuk Anda.
andlrc
5

Solusi cepat untuk layanan GWT-RPC adalah menambahkan ini ke semua metode jarak jauh:

getThreadLocalResponse().setHeader("Cache-Control", "no-cache");
Lars Høidahl
sumber
Sebagian besar dari kita memiliki ratusan metode jarak jauh dalam penyebaran GWT mereka. Apakah ada cara universal mengatur header kontrol cache untuk semua permintaan?
dirkoneill
5

Ini adalah pembaruan dari jawaban Baz1nga. Karena options.databukan objek tetapi string saya hanya terpaksa menyatukan cap waktu:

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
  if (originalOptions.type == "post" || options.type == "post") {

    if (options.data && options.data.length)
      options.data += "&";
    else
      options.data = "";

    options.data += "timeStamp=" + new Date().getTime();
  }
});
remcoder
sumber
1
Menambahkan cap waktu adalah ide yang buruk, coba solusi Dave sebagai gantinya.
Nicholas Shanks
4

Untuk mengatasi masalah ini untuk WebApps ditambahkan ke layar beranda, kedua solusi terpilih harus diikuti. Caching perlu dimatikan pada server web untuk mencegah permintaan baru agar tidak di-cache maju dan beberapa input acak perlu ditambahkan ke setiap permintaan posting agar permintaan yang telah di-cache untuk melewati. Silakan merujuk ke posting saya:

iOS6 - Apakah ada cara untuk menghapus permintaan ajax POST cache untuk webapp yang ditambahkan ke layar beranda?

PERINGATAN: untuk siapa saja yang menerapkan solusi dengan menambahkan stempel waktu untuk permintaan mereka tanpa mematikan caching di server. Jika aplikasi Anda ditambahkan ke layar beranda, SETIAP respons pos sekarang akan di-cache, membersihkan cache safari tidak menghapusnya dan sepertinya tidak kedaluwarsa. Kecuali jika seseorang memiliki cara untuk membersihkannya, ini terlihat seperti potensi kebocoran memori!

fbader
sumber
Apakah semua tanggapan akan di-cache ke file atau memori di telepon?
Eydun
Ini tidak terjadi pada saya. Saya menambahkan cap waktu ke url saya (bukan parameter posting) dan berfungsi dengan baik, baik saat browsing dari safari dan saat menyimpan ke layar beranda.
ShadeTreeDeveloper
4

Hal-hal yang TIDAK BEKERJA bagi saya dengan iPad 4 / iOS 6:

Permintaan saya mengandung: Cache-Control: no-cache

//asp.net's:
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache)

Menambahkan cache: false ke panggilan ajax jQuery saya

 $.ajax(
        {
            url: postUrl,
            type: "POST",
            cache: false,
            ...

Hanya ini yang berhasil:

var currentTime = new Date();
var n = currentTime.getTime();
postUrl = "http://www.example.com/test.php?nocache="+n;
$.post(postUrl, callbackFunction);
Brian Ogden
sumber
Untuk apa suara turun? Ini adalah cache informasi penting: false tidak berfungsi dengan iPad4 / iOS6 juga //asp.net's: HttpContext.Current.Response.Cache.SetCacheability (HttpCacheability.NoCache)
Brian Ogden
Untuk anak cucu: pada 2017, $.ajax cache: falsetambahkan url dengan parameter kueri _=Date.prototype.getTime(), jadi menambahkan cap waktu secara manual tidak lagi diperlukan.
cowbert
3

Itulah yang harus dilakukan untuk GWT-RPC

class AuthenticatingRequestBuilder extends RpcRequestBuilder 
{
       @Override
       protected RequestBuilder doCreate(String serviceEntryPoint) 
       {
               RequestBuilder requestBuilder = super.doCreate(serviceEntryPoint);           
               requestBuilder.setHeader("Cache-Control", "no-cache");

               return requestBuilder;
       }
}

AuthenticatingRequestBuilder builder = new AuthenticatingRequestBuilder();
((ServiceDefTarget)myService).setRpcRequestBuilder(builder);    
Spiff
sumber
2

Solusi saya di ASP.NET (pagemethods, layanan web, dll.)

protected void Application_BeginRequest(object sender, EventArgs e)
{
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
}
Alexandre
sumber
1

Sementara menambahkan parameter cache-buster untuk membuat permintaan tampak berbeda tampaknya seperti solusi yang solid, saya akan menyarankan untuk tidak melakukannya, karena itu akan merusak aplikasi yang bergantung pada caching aktual yang terjadi. Membuat API menghasilkan header yang benar adalah solusi terbaik, bahkan jika itu sedikit lebih sulit daripada menambahkan penghilang cache ke pemanggil.

Ivo Jansch
sumber
1
Sementara saya akan setuju dengan Anda sebagian besar keadaan, saya berpendapat bahwa solusi nyata untuk masalah ini adalah Apple menerapkan HTTP dengan benar. Dengan pemikiran ini, saya tidak akan menyalahkan banyak pengembang untuk menerapkan solusi paling sederhana hingga saat itu. Bagi saya, memodifikasi implementasi jquery adalah perbaikan paling sederhana karena memungkinkan saya untuk membuat satu edit dan yakin itu aktif untuk seluruh situs saya.
Sam Shiles
1

Bagi mereka yang menggunakan Struts 1, berikut adalah cara saya memperbaiki masalah ini.

web.xml

<filter>
    <filter-name>SetCacheControl</filter-name>
    <filter-class>com.example.struts.filters.CacheControlFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>SetCacheControl</filter-name>
    <url-pattern>*.do</url-pattern>
    <http-method>POST</http-method>
</filter-mapping>

com.example.struts.filters.CacheControlFilter.js

package com.example.struts.filters;

import java.io.IOException;
import java.util.Date;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;

public class CacheControlFilter implements Filter {

        public void doFilter(ServletRequest request, ServletResponse response,
                     FilterChain chain) throws IOException, ServletException {

        HttpServletResponse resp = (HttpServletResponse) response;
        resp.setHeader("Expires", "Mon, 18 Jun 1973 18:00:00 GMT");
        resp.setHeader("Last-Modified", new Date().toString());
        resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0");
        resp.setHeader("Pragma", "no-cache");

        chain.doFilter(request, response);
    }

    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void destroy() {
    }

}
cbmeeks
sumber
1

Saya dapat memperbaiki masalah saya dengan menggunakan kombinasi $ .ajaxSetup dan menambahkan stempel waktu ke url posting saya (bukan ke parameter post / body). Ini berdasarkan rekomendasi dari jawaban sebelumnya

$(document).ready(function(){
    $.ajaxSetup({ type:'POST', headers: {"cache-control","no-cache"}});

    $('#myForm').submit(function() {
        var data = $('#myForm').serialize();
        var now = new Date();
        var n = now.getTime();
        $.ajax({
            type: 'POST',
            url: 'myendpoint.cfc?method=login&time='+n,
            data: data,
            success: function(results){
                if(results.success) {
                    window.location = 'app.cfm';
                } else {
                    console.log(results);
                    alert('login failed');
                }
            }
        });
    });
});
ShadeTreeDeveloper
sumber
1

Saya pikir Anda sudah menyelesaikan masalah Anda, tetapi izinkan saya berbagi ide tentang caching web.

Memang benar Anda dapat menambahkan banyak header di setiap bahasa yang Anda gunakan, sisi server, sisi klien, dan Anda dapat menggunakan banyak trik lain untuk menghindari caching web, tetapi selalu berpikir bahwa Anda tidak pernah tahu dari mana klien terhubung ke server Anda, Anda tidak pernah tahu apakah dia menggunakan koneksi Hotel "Hot-Spot" yang menggunakan Squid atau produk caching lainnya.

Jika pengguna menggunakan proxy untuk menyembunyikan posisi aslinya, dll ... satu - satunya cara nyata untuk menghindari caching adalah cap waktu dalam permintaan juga jika tidak digunakan.

Sebagai contoh:

/ajax_helper.php?ts=3211321456

Kemudian setiap cache manager yang Anda lewati tidak menemukan URL yang sama di repositori cache dan kembali mengunduh konten halaman.

Lanello
sumber
Jawaban lama, tetapi dua sen saya: Ini umumnya saran yang bagus dan dipahami oleh sebagian besar pengembang web yang kompeten, tetapi dalam kasus spesifik jQuery, jika Anda membuat $.ajaxdan telah menetapkan opsi untuk memilikinya {cache:false}maka jQuery sendiri secara otomatis akan menambahkan penghilang cache di belakang layar tanpa Anda perlu melakukan hal lain.
JakeGould
0

Tergantung pada aplikasinya, Anda dapat memecahkan masalah sekarang di iOS 6 menggunakan Safari> Advanced> Web Inspector sehingga membantu dengan situasi ini.

Hubungkan ponsel ke Safari di Mac dan kemudian gunakan menu pengembang untuk memecahkan masalah aplikasi web.

Bersihkan data situs web pada iPhone setelah pembaruan ke iOS6, termasuk khusus untuk aplikasi menggunakan Tampilan Web. Hanya satu aplikasi memiliki masalah dan ini diselesaikan selama pengujian IOS6 Beta jalan kembali, sejak saat itu tidak ada masalah nyata.

Anda mungkin perlu melihat aplikasi Anda juga, periksa NSURLCache jika di WebView di aplikasi khusus.

https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSURLCache_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40003754

Saya kira tergantung pada sifat sebenarnya dari masalah Anda, implementasi, dll.

Ref: $ .ajax calls

Steven Strauss
sumber
Meskipun ini tidak secara langsung menjawab pertanyaan awal, ini adalah informasi yang sangat berguna untuk dapat memecahkan masalah pada perangkat secara umum, jadi saya memilihnya.
Kris Giesing
0

Saya menemukan satu solusi yang membuat saya penasaran mengapa itu berhasil. Sebelum membaca jawaban Tadej mengenai layanan web ASP.NET, saya mencoba untuk membuat sesuatu yang bisa digunakan.

Dan saya tidak mengatakan itu solusi yang baik, tetapi saya hanya ingin mendokumentasikannya di sini.

halaman utama: termasuk fungsi JavaScript, checkStatus (). Metode ini memanggil metode lain yang menggunakan panggilan jQuery AJAX untuk memperbarui konten html. Saya menggunakan setInterval untuk memanggil checkStatus (). Tentu saja, saya mengalami masalah caching.

Solusi: gunakan halaman lain untuk memanggil pembaruan.

Di halaman utama, saya menetapkan variabel boolean, runUpdate, dan menambahkan yang berikut ini ke tag body:

<iframe src="helper.html" style="display: none; visibility: hidden;"></iframe>

Di helper.html:

<meta http-equiv="refresh" content="5">
<script type="text/javascript">
    if (parent.runUpdate) { parent.checkStatus(); }
</script>

Jadi, jika checkStatus () dipanggil dari halaman utama, saya mendapatkan konten yang di-cache. Jika saya memanggil checkStatus dari halaman anak, saya mendapatkan konten yang diperbarui.

CM Kanode
sumber
0

Sementara halaman masuk dan pendaftaran saya berfungsi seperti pesona di Firefox, IE dan Chrome ... Saya telah berjuang dengan masalah ini di Safari untuk iOS dan OSX, beberapa bulan yang lalu saya menemukan solusi di SO.

<body onunload="">

ATAU via javascript

<script type="text/javascript">
window.onunload = function(e){
    e.preventDefault();
    return;
};
</script>   

Ini adalah hal yang jelek tapi berhasil untuk sementara waktu.

Saya tidak tahu mengapa, tetapi mengembalikan nol ke onunloadacara halaman tidak di-cache di Safari.

Adriano Rosa
sumber
0

Kami menemukan bahwa iPhone dan iPad yang lebih lama, yang menjalankan versi iOS 9 & 10, kadang-kadang mengembalikan hasil AJAX yang kosong, mungkin karena Apple menurunkan kecepatan CPU. Saat mengembalikan hasil kosong, iOS tidak memanggil server, seolah-olah mengembalikan hasil dari cache. Frekuensi sangat bervariasi, dari sekitar 10% hingga 30% dari panggilan AJAX kembali kosong.

Solusinya sulit dipercaya. Tunggu saja 1 dan panggil lagi. Dalam pengujian kami, hanya satu pengulangan yang diperlukan, tetapi kami menulis kode untuk menelepon hingga 4 kali. Kami tidak yakin apakah menunggu 1s diperlukan, tetapi kami tidak ingin mengambil risiko membebani server kami dengan semburan panggilan berulang.

Kami menemukan masalah terjadi dengan dua panggilan AJAX yang berbeda, memanggil file API yang berbeda dengan data yang berbeda. Tapi saya khawatir itu bisa terjadi pada panggilan AJAX apa pun. Kami hanya tidak tahu karena kami tidak memeriksa setiap hasil AJAX dan kami tidak menguji setiap panggilan beberapa kali pada perangkat lama.

Kedua masalah panggilan AJAX menggunakan: POST, Asynchronous = true, setRequestHeader = ('Content-Type', 'application / x-www-form-urlencoded')

Ketika masalah terjadi, biasanya hanya ada satu panggilan AJAX yang terjadi. Jadi itu bukan karena tumpang tindih panggilan AJAX. Kadang-kadang masalah terjadi ketika perangkat sibuk, tetapi kadang-kadang tidak, dan tanpa DevTools kita tidak benar-benar tahu apa yang terjadi pada saat itu.

iOS 13 tidak melakukan ini, juga Chrome atau Firefox. Kami tidak memiliki perangkat uji yang menjalankan iOS 11 atau 12. Mungkin orang lain dapat mengujinya?

Saya mencatat ini di sini karena pertanyaan ini adalah hasil teratas Google ketika mencari masalah ini.

CaptureWiz
sumber
-1

Ini bekerja dengan ASP.NET hanya setelah menambahkan pragma:no-cacheheader di IIS . Cache-Control: no-cachetidak cukup.

Boris
sumber
-2

Saya menyarankan solusi untuk mengubah tanda tangan fungsi menjadi sesuatu seperti ini:

getNewRecordID (intRecordType, strTimestamp) dan kemudian selalu meneruskan parameter TimeStamp juga, dan buang saja nilai itu di sisi server. Ini mengatasi masalah ini.

fred1234
sumber