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:
  1. var BaseURL = window.location.protocol + '//' + window.location.hostname + '/';  
  2. var Ora = document.createElement('img');  
  3. Ora.setAttribute('src', BaseURL + 'elérési_út/ora_02.gif');  
  4. setTimeout('Usercheck()', 60000);  
  5.   
  6. function Usercheck() {  
  7.     var Height = $('#login_box').height();  
  8.     var Width  = $('#login_box').width();  
  9.     $('#login_box').html('');  
  10.     $('#login_box').append(Ora);  
  11.     $('#login_box').height(Height);  
  12.     $('#login_box').width(Width);  
  13.     $('#login_box').load(BaseURL + 'ajax/user_refresh/'function() {  
  14.         if ($('#login_box').children().is("form[name='login_form']")) {  
  15.             $('#message').html('<h5 class="red">Figyelem!</h5>' +  
  16.                                '<p class="red">A rendszer Önt kiléptette, a tartalmat nem tudja menteni.</p>');  
  17.             window.scrollTo(0, 0);  
  18.             $('#admin_menu').hide(1000);  
  19.         } else {  
  20.             setTimeout('Usercheck()', 60000);  
  21.         }  
  22.     });  
  23. }  
(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.
  1. angular.module('interceptors', [])  
  2.     .config(function ($httpProvider) {  
  3.         $httpProvider.requestInterceptors.push('httpRequestInterceptorIECacheSlayer');  
  4.     })  
  5.     // IE 8 cache problem - Request Interceptor - https://github.com/angular/angular.js/issues/1418#issuecomment-11750815  
  6.     .factory('httpRequestInterceptorIECacheSlayer'function($log) {  
  7.         return function(promise) {  
  8.             return promise.then(function(request) {  
  9.                 // If not a partial, append timestamp query string  
  10.                 if(request.url.indexOf("partials/") == -1) {  
  11.                     var d = new Date();  
  12.                     request.url = request.url + '?cacheSlayer=' + d.getTime();  
  13.                 }  
  14.                 $log.info('request.url = ' + request.url);  
  15.                 // return the config object to pass it on to the next interceptor  
  16.                 return request;  
  17.             });  
  18.         }  
  19.     });  
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é.
  1. response.addHeader "Cache-Control""max-age=0,no-cache,no-store,post-check=0,pre-check=0";  
  2. 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:
  1. $('#login_box').html('')    
  2.     .append(Ora)    
  3.     .height(Height)    
  4.     .width(Width)    
  5.     .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.