ugrás a tartalomhoz

Ajax hol van - hol nincs

Pepita · 2013. Feb. 7. (Cs), 12.32
Sziasztok!

Adott egy oldal, ahol a bejelentkezett felhasználóknak timelimit is van a http kérések közt. Ha letelt -> logout. Viszont van olyan szerkesztői funkció (Hírfeltöltés), ahol nem biztos, hogy elég ez az idő a POST-ig, emiatt egy kis (jquery1.4-) ajax-frissítéssel ezen az oldalon áthidalom:

var BaseURL = window.location.protocol + '//' + window.location.hostname + '/';
var Ora = document.createElement('img');
Ora.setAttribute('src', BaseURL + 'elérési_út/ora_02.gif');
setTimeout('Usercheck()', 60000);

function Usercheck() {
	var Height = $('#login_box').height();
	var Width  = $('#login_box').width();
	$('#login_box').html('');
	$('#login_box').append(Ora);
	$('#login_box').height(Height);
	$('#login_box').width(Width);
	$('#login_box').load(BaseURL + 'ajax/user_refresh/', function() {
		if ($('#login_box').children().is("form[name='login_form']")) {
			$('#message').html('<h5 class="red">Figyelem!</h5>' +
							   '<p class="red">A rendszer Önt kiléptette, a tartalmat nem tudja menteni.</p>');
			window.scrollTo(0, 0);
			$('#admin_menu').hide(1000);
		} else {
			setTimeout('Usercheck()', 60000);
		}
	});
}
(Bocs a hosszú kódért.)
Természetesen az 'ajax/user_refresh/' controller és fv. létezik, és vissza is adja a kívánt tartalmat. (Van mindenféle ellenőrzés is, nincs-e letiltva a Júzer, stb., de ez itt nem lényeg.)

Ez így rendben is ment - localhoston. Viszont élesben (másik gépről nézve) IE8 nem mindig küldi el a kérést, csak az órát teszi ki egy pillanatra, de adatforgalom nincs egy byte se. Ilyenkor egy pillanatra megy ki az óra, majd a #login_box előző tartalma.

Miért?
Ha ilyen kis rész-HTML-t küldök ki szerveroldalról, akkor használhatok rá headert? (no-cache) Bár nem hiszem, hogy megoldaná a dolgot, ha a kérés se megy el.

Van egy másik oldal is, ahol majdnem ugyanezt alkalmazom, csak ott az oldalon kattintásra megy (menne) a kérés, ha az előző kattintás óta már telt el egy perc.

(Nyilván lehetne szebb-jobb js-t írni rá, ilyen észrevételt is szívesen veszek, de elsősorban a hiba oka érdekelne.)
 
1

Ha jól emlékszem van ajax

inf · 2013. Feb. 7. (Cs), 12.45
Ha jól emlékszem van ajax cache bug ie8-nál, próbálj meg querystring-ben utána tenni timestamp-et, akkor biztosan működni fog. Mindjárt utánakeresek, hogy pontosan mi is ez, hátha header-el is megoldható...

jquery javítás - gyakorlatilag ugyanazt csinálja, mint amit fentebb is írtam, szóval kliens oldalról oldja meg a problémát...

Elméletileg csak GET request-nél jelentkezik a probléma, szóval hacsak nem REST elveket sértesz, akkor használhatsz POST-ot helyette, az megoldja. A nocache header-el is lehet próbálkozni, de nagy valószínűséggel annak nem lesz hatása.

angular.module('interceptors', [])
    .config(function ($httpProvider) {
        $httpProvider.requestInterceptors.push('httpRequestInterceptorIECacheSlayer');
    })
    // IE 8 cache problem - Request Interceptor - https://github.com/angular/angular.js/issues/1418#issuecomment-11750815
    .factory('httpRequestInterceptorIECacheSlayer', function($log) {
        return function(promise) {
            return promise.then(function(request) {
                // If not a partial, append timestamp query string
                if(request.url.indexOf("partials/") == -1) {
                    var d = new Date();
                    request.url = request.url + '?cacheSlayer=' + d.getTime();
                }
                $log.info('request.url = ' + request.url);
                // return the config object to pass it on to the next interceptor
                return request;
            });
        }
    });
Az eddigi kedvenc :D "IE cache slayer" :D

Elvileg a response header is működik.

Nem csak IE-vel van gond, régi opera és safari is bugos többé-kevésbé.

response.addHeader "Cache-Control", "max-age=0,no-cache,no-store,post-check=0,pre-check=0";
response.addHeader "Expires", "Mon, 26 Jul 1997 05:00:00 GMT"
IE8-nak elég a no-cache, no-store, IE7-nél kell post-check és pre-check is. Körülbelül ennyi a szerver oldali megoldása, már ha nem hazudnak :-P

Ha ilyen kis rész-HTML-t küldök ki szerveroldalról, akkor használhatok rá headert? (no-cache) Bár nem hiszem, hogy megoldaná a dolgot, ha a kérés se megy el.

Nem biztos, hogy teljesen érted a böngésző cache koncepcióját, ha megtalálja a cuccot, amit keresel a cache-ben, akkor onnan szolgálja ki, ezért nem megy kérés a szerver felé... Először javítani kell a kódon, hogy kiküldje a no-cache header-t, utána meg üríteni kell a cache-t, és csak utána újra próbálni, hogy megy e.
2

Köszönöm szépen!

Pepita · 2013. Feb. 7. (Cs), 13.15
Na, ezért nem barátom a js... Illetve inkább a kliensoldal.

Nagyon köszönöm a részletes választ, azt hiszem ebben az (két) esetben maradok a +timestamp-nél. Szerveroldalon meg eldobom... :)
Azt viszont nem értem, hogy tesztkörnyezetben miért működött szintén IE8-al is. Lehet, hogy tiltva volt akkor a cache? Mindenesetre örülök, hogy ilyen egyszerűen is gyógyítható.
3

Gyorstárazás

Hidvégi Gábor · 2013. Feb. 7. (Cs), 13.22
Rögtön feltűnt, hogy egyvalami sokszor ismétlődik a kódodban: $('#login_box'). Nem ismerem a jQuery-t, de biztos vagyok benne, hogy ilyen esetekre ő is eltárolja az elemeket egy belső tömbjében, viszont ekkor is elég sok kódnak le kell futnia, amíg ezt az elemet visszakapod. Ezért érdemes inkább így megcsinálni:

var login box = $('#login_box');
login_box.append(Ora);
login_box.append(Height);
...
4

Köszi

Pepita · 2013. Feb. 7. (Cs), 13.27
A példád harmadik sora viszont nem append, nem kötöszködésből, csak a rend kedvéért. Köszönöm az optimalizációt.
5

optimailizáljunk még!

szabo.b.gabor · 2013. Feb. 7. (Cs), 21.40
szóval a jquery annyira májer, hogy ha olyan utasítást adsz neki, ami nem adna vissza semmit, akkor visszaadja önmagát. tehát:
$('#login_box').html('')  
    .append(Ora)  
    .height(Height)  
    .width(Width)  
    .load(blabla..);
6

Még a végén megkedvelem :)

Pepita · 2013. Feb. 7. (Cs), 23.02
Én viszont nem vagyok ennyire májer, ill. szeretem tudni később is, hogy mit-miért-hogy csináltam. De nagyobb kódoknál hasznos lehet. Hasonlót követtem már el, de nem nagyon szeretem, mert - számomra - nem elég átlátható. Nekem jobb, ha egy utasítás egy sor, de érdekes.
7

Szerintem teljesen átlátható

inf · 2013. Feb. 8. (P), 01.51
Szerintem teljesen átlátható ez a forma. Mondjuk clean code-ban train wreck anti pattern-nek hívják, és jobb szeretik több sorba szétszedni, vagy elfedni egy függvénnyel. Js-ben szerintem annyira nem rontja az átláthatóságot, legalábbis elég érthető, hogy mi történik...
8

Vonatroncsok

T.G · 2013. Feb. 8. (P), 11.12
Szerintem az más! A probléma akkor van, amikor nem ugyanaz az objektum:
item.getParent().getNextsibling().getFirstChild().get...
És ezzel tényleg probléma van, könnyen elveszti az ember a fonalat, hogy na akkor most pontosan mivel is foglalkozunk. Illetve a Demeter törvényének is ellentmond.
9

Ja igazad van, ez tényleg

inf · 2013. Feb. 9. (Szo), 17.21
Ja igazad van, ez tényleg más.