Framework Ajax per AGGIORNAMENTI di CONTENUTI tramite richieste simultantee e temporizzate
so bene che esistono a decine di framework javascript-ajax e di soluzioni da voi sviluppate,
cercando su google ed leggendo le guide di html.it c'è veramente di tutto,
tuttavia ho sempre timore nell'applicare pacchetti di codice alla cieca,
sia perchè non ho il controllo della situazione, sia perchè di solito a me serve il 10% delle loro potenzialità quindi causerei appesantimenti in kb inutili
è così che con l'aiuto di:
- l'ottima guida di Html.it
- il curioso esempio di Handling Multiple XMLHTTPRequest Objects
ho prodotto una mia soluzione, che ho deciso di condividere con voi
impegnandomi a migliorarla sotto i vostri consigli
Uso
UpdtAjaxRqstInsr (Cosa,ConCosa [,AttesaMassima [,TraQuanto [,QuanteVolte [,OgniQuanto]]]]);
parametri obbligatori:
Cosa= nome del tag in cui inserire il risultato
ConCosa= url completo e assoluto da caricare
parametri opzionali del timing:
AttesaMassima= secondi di massima attesa, oltre i quali chiude la richiesta
TraQuanto= secondi di attesa prima di inviare la richiesta
QuanteVolte= numero di volte che voglio sia ripetuta la richiesta
OgniQuanto= secondo di attesa tra il termine di una richiesta e la ripetizione successiva
Funzionalità
- c'è la verifica del supporto ajax da parte del browser: se non supportato restituisce true in modo da attivare l'eventuale <A> da cui parte la richiesta
- nel tag di destinazione viene caricata una immagine di loading
- click multipli metteranno in coda più richieste identiche (ma bisogna essere scemi perchè il loading compare), prevedere una disabilitazione del bottone che ha inviato la richiesta credo che vincoli nell'uso di un tag preciso, invece voglio che sia tutto libero
- prevede un monitoraggio delle attività per le modalità di debugging: un div fa da logger delle richieste inviate al server, ed un altro mostra la coda di attesa contenuta nell'array
- le richieste possono esser effettuate col metodo Post e Get in contemporanea, è sufficiente usare un url con la query string già impostata, ed eventualmente il parametro Cosa per passare una variabile via get ...è chiaro che quest'ultima riga di codice dovete personalizzarla, poichè la mia soluzione è ad hoc per le mie esigenze: io indico al server con Cosa come personalizzare l'output
Logica di Funzionamento
Uso una Array per accodare tutte le richieste ajax da eseguire, dove il campo Stato contiene 1 se la richiesta è aperta, ed il campo Quando contiente l'ora programmata per l'esecuzione della richiesta.
Tramite la funzione UpdtAjaxRqstInsr(...) inserisco una richiesta nell'array e avvio i cicli di controllo delle richieste, che periodicamente ogni secondo vengono eseguite dalla funzione UpdtAjaxRqstChck, che controlla il timing ed effettua le richieste ajax tramite la funzione UpdtAjaxRqstSend
Note di Programmazione
- le variabili hanno nomi con parole sintetizzate dalle prime 4 consonanti
- sicuramente la sintassi può essere ampiamente ottimizzata, aspetto vostri consigli
- mi si poneva il problema che se nello stesso istante la 1^ e 2^ funzione fossero eseguite in contemporanea avrebbe funzionato male poichè 1 leggeva ed 1 scriveva sullo stesso array, per questo ho creato 1 variabile che permettesse alla prima funzione di posticiparsi di 0,1sec qualora la seconda funzione fosse in funzione
Cosa dovete personalizzare
- Path e Nome dell'immagine di loading
- Parametri di timing di default (se vi va)
- l'uso della variabile passata tramite metodo post
Codice PHP:
function UpdtAjaxRqstInsr (Cosa,ConCosa,AttesaMassima,TraQuanto,QuanteVolte,OgniQuanto) {
// VERIFICHE PRELIMINARI: se altre funzioni stanno lavorando sull'array, temporeggio 0,1sec
if(typeof(UpdtAjaxRqstChckStts)=='undefined') UpdtAjaxRqstChckStts=0; else if (UpdtAjaxRqstChckStts==1) { setTimeout('UpdtAjaxRqstInsr (Cosa,ConCosa,AttesaMassima,TraQuanto,QuanteVolte,OgniQuanto);',100); return false; }
// VERIFICHE PRELIMINARI: controllo variabili tempo; l'input è in secondi, convertito poi in millisecondi
if(!AttesaMassima) AttesaMassima=15000; else AttesaMassima*=1000;
if(!TraQuanto) TraQuanto=0; else TraQuanto*=1000;
if(!QuanteVolte) QuanteVolte=1;
if(!OgniQuanto) OgniQuanto=0; else OgniQuanto*=1000;
// VERIFICHE PRELIMINARI: Supportato = dice se Ajax è supportato dal browser e determina il return per link di origine: se false funzionerà il tag <A>
UpdtAjaxRqstSppr=false;
browserUtente = navigator.userAgent.toUpperCase();
if(typeof(XMLHttpRequest) === "function" || typeof(XMLHttpRequest) === "object") UpdtAjaxRqstSppr=true;
else if(window.ActiveXObject && browserUtente.indexOf("MSIE 4") < 0) UpdtAjaxRqstSppr=true;
// EXE: se c'è supporto ajax allora accoda richiesta e verifico che i controlli dell'handler siano attivi
if(UpdtAjaxRqstSppr==true){
//piazza il loading nel div
document.getElementById(Cosa).innerHTML='[img]Loading.gif[/img]';
//se non c'è l'handler lo creo
if(typeof(UpdtAjaxRqstList)=='undefined') UpdtAjaxRqstList = new Array;
//accoda all'handler
dataChiamata=new Date(), Quando=dataChiamata.getTime()+TraQuanto;
i=UpdtAjaxRqstList.length
UpdtAjaxRqstList[i]= new Array;
UpdtAjaxRqstList[i]['Stato']=0;
UpdtAjaxRqstList[i]['Cosa']=Cosa;
UpdtAjaxRqstList[i]['ConCosa']=ConCosa;
UpdtAjaxRqstList[i]['Quando']=Quando;
UpdtAjaxRqstList[i]['QuanteVolte']=QuanteVolte;
UpdtAjaxRqstList[i]['OgniQuanto']=OgniQuanto;
UpdtAjaxRqstList[i]['AttesaMassima']=AttesaMassima;
//attiva l'esecuzione dell'handler
if(typeof(UpdtAjaxRqstChckIdnt)=='undefined') UpdtAjaxRqstChckIdnt='';
if(!UpdtAjaxRqstChckIdnt || UpdtAjaxRqstChckIdnt==''){
setTimeout('UpdtAjaxRqstChck()',0); //altrimenti abbiamo il primo secondo di pausa, poichè set interval (che al caso nostro) parte dopo la pausa
UpdtAjaxRqstChckIdnt=setInterval('UpdtAjaxRqstChck()',1000);
}
return false;
}else{
return true;
}
}
function UpdtAjaxRqstChck() {
UpdtAjaxRqstStby=0; // Standby = dice se c'è ancora qualcosa sul fuoco, ovvero di volta in volta se ci sono richieste aperte e/o da eseguire ancora
UpdtAjaxRqstChckStts=1; // Check Status = 1 significa che questa funzione è in esecuzione e quindi non si può toccare l'array, alla fine tornerà 0
// verifico a che punto è l'eventuale richiesta aperta
// posiziona la richiesta con Stato=1 al primo posto
UpdtAjaxRqstList.sort(function(a,b){return a.Stato<b.Stato});
if(UpdtAjaxRqstList[0]['Stato']==1){
// se ha finito pubblico
if(UpdtAjaxRqst.readyState === 4){
if(UpdtAjaxRqst.status == 200)
document.getElementById(UpdtAjaxRqstList[0]['Cosa']).innerHTML= UpdtAjaxRqst.responseText;
else
document.getElementById(UpdtAjaxRqstList[0]['Cosa']).innerHTML= 'Richiesta Fallita. Riprova.';
UpdtAjaxRqstList[0]['QuanteVolte']--;
if(UpdtAjaxRqstList[0]['QuanteVolte']>0){
UpdtAjaxRqstList[0]['Quando']+= UpdtAjaxRqstList[0]['OgniQuanto'];
UpdtAjaxRqstList[0]['Stato']=0;
// tolgo la riga
} else UpdtAjaxRqstList.splice(0,1);
// se non ha finito verifico il tempo
}else{
var data=new Date(), data=data.getTime();
if(UpdtAjaxRqstList[0]['AttesaMassima'] > data-UpdtAjaxRqstList[0]['Quando']) UpdtAjaxRqstStby=1;
else{ document.getElementById(UpdtAjaxRqstList[0]['Cosa']).innerHTML= 'Richiesta Scaduta. Riprova.';
UpdtAjaxRqstList[0]['QuanteVolte']--;
if(UpdtAjaxRqstList[0]['QuanteVolte']>0){
UpdtAjaxRqstList[0]['Quando']+= UpdtAjaxRqstList[0]['OgniQuanto'];
UpdtAjaxRqstList[0]['Stato']=0;
// tolgo la riga
} else UpdtAjaxRqstList.splice(0,1);
}
}
}
// verifico l'eventuali righe ferme se non ce ne sono di aperte
if(UpdtAjaxRqstStby==0 && UpdtAjaxRqstList.length>0){
UpdtAjaxRqstStby=1;
// posiziona le richieste in ordine cronologico
UpdtAjaxRqstList.sort(function(a,b){return a.Quando>b.Quando});
var data=new Date(), data=data.getTime();
if(UpdtAjaxRqstList[0]['Quando']<data){
UpdtAjaxRqstList[0]['Stato']=1;
UpdtAjaxRqstList[0]['Quando']=data;
UpdtAjaxRqstSend (UpdtAjaxRqstList[0]['Cosa'], UpdtAjaxRqstList[0]['ConCosa']);
}
}
//aggiorna status ajax-debugger
var codice='';
for(var i=0;i<UpdtAjaxRqstList.length;i++)
codice+=
'Stato='+UpdtAjaxRqstList[i]['Stato']+
' Quando='+UpdtAjaxRqstList[i]['Quando']+
' QuanteVolte='+UpdtAjaxRqstList[i]['QuanteVolte']+
' OgniQuanto='+UpdtAjaxRqstList[i]['OgniQuanto']+
' AttesaMassima='+UpdtAjaxRqstList[i]['AttesaMassima']+
' Cosa='+UpdtAjaxRqstList[i]['Cosa']+
' ConCosa='+UpdtAjaxRqstList[i]['ConCosa']+
'
';
if(document.getElementById('AjaxStts')) document.getElementById('AjaxStts').innerHTML=codice;
// se le righe sono finite disattiva il controllo
if(UpdtAjaxRqstStby==0) { clearTimeout(UpdtAjaxRqstChckIdnt); UpdtAjaxRqstChckIdnt=''; }
UpdtAjaxRqstChckStts=0;
}
function UpdtAjaxRqstSend(Cosa,ConCosa) {
// assegnazione oggetto ajax, di sicuro supportato se siamo arrivati qui
browserUtente = navigator.userAgent.toUpperCase();
if(typeof(XMLHttpRequest) === "function" || typeof(XMLHttpRequest) === "object")
UpdtAjaxRqst = new XMLHttpRequest();
else if(window.ActiveXObject && browserUtente.indexOf("MSIE 4") < 0) {
// se non esiste l'unica possibilità è ActiveX di IE5+
if(browserUtente.indexOf("MSIE 5") < 0) UpdtAjaxRqst = new ActiveXObject("Msxml2.XMLHTTP");
else UpdtAjaxRqst = new ActiveXObject("Microsoft.XMLHTTP");
}
UpdtAjaxRqst.open('POST', ConCosa, true); // impostazione richiesta asincrona in GET del file specificato
UpdtAjaxRqst.setRequestHeader("connection", "close"); // rimozione dell'header "connection" come "keep alive"
UpdtAjaxRqst.setRequestHeader("content-type", "application/x-www-form-urlencoded"); // necessario per l'invio di variabili con POST
UpdtAjaxRqst.send('ajax='+Cosa); // invio richiesta
//aggiorna log ajax-debugger
if(document.getElementById('AjaxLogg')) document.getElementById('SrCmndAjaxLogg').innerHTML+=Cosa+" "+ConCosa+"
";
}
eventuale box per il debugging:
Codice PHP:
_ _ _ _ Ajax Status _ _ _ _<div id="AjaxStts"></div>
_ _ _ _ Ajax Logger _ _ _ _<div id="AjaxLogg"></div>
allora? ve piaqque?
:ignore: