1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
---
title: Iniziare
slug: Web/Guide/AJAX/Iniziare
tags:
- AJAX
- Tutte_le_categorie
translation_of: Web/Guide/AJAX/Getting_Started
---
<p> </p>
<p>Questo articolo spiega le fondamenta di AJAX e fornisce due semplici esempi per iniziare.</p>
<h3 id="Cos.27.C3.A8_AJAX.3F" name="Cos.27.C3.A8_AJAX.3F">Cos'è AJAX?</h3>
<p>AJAX (Asynchronous JavaScript and XML) è un termine coniato recentemente per descrivere due utili funzionalità che sono presenti nei browser da anni, ma che sono state sottovalutate dalla maggioranza degli sviluppatori web fino a quando, di recente, alcune applicazioni come Gmail, Google suggest e Google Maps le hanno portate in auge.</p>
<p>Le funzionalità di cui stiamo parlando sono:</p>
<ul>
<li>la possibilità di eseguire richieste al server senza ricaricare la pagina</li>
<li>la possibilità di interpretare e lavorare con i documenti XML</li>
</ul>
<h3 id="Passo_1_.E2.80.93_D.C3.AC_.22per_favore.22.2C_o_Come_fare_una_richiesta_HTTP" name="Passo_1_.E2.80.93_D.C3.AC_.22per_favore.22.2C_o_Come_fare_una_richiesta_HTTP">Passo 1 – Dì "per favore", o Come fare una richiesta HTTP</h3>
<p>Per effettuare una richiesta HTTP al server utilizzando JavaScript, si utilizza un'istanza di una classe che fornisce detta funzionalità. Tale classe è stata introdotta originariamente in Internet Explorer come oggetto ActiveX e si chiamava <code>XMLHTTP</code>. Successivamente Mozilla, Safari e altri browser hanno implementato la classe <code>XMLHttpRequest</code>, che supporta gli stessi metodi e le stesse proprietà della classe di Microsoft.</p>
<p>Il risultato è che per creare un'istanza (oggetto) da tale classe che funzioni sui diversi browser, occorre scrivere un codice simile al seguente:</p>
<pre>if (window.XMLHttpRequest) { // Mozilla, Safari, ...
http_request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
http_request = new ActiveXObject("Microsoft.XMLHTTP");
}
</pre>
<p>(Per scopi illustrativi, il codice qui riportato è una versione leggermente semplificata del codice generalmente utilizzato per creare un'istanza XMLHTTP. Per un esempio più pratico, si veda il Passo 3 di questo articolo)</p>
<p>Certe versioni di alcuni browser della famiglia Mozilla, non si comportano correttamente nel caso in cui la risposta del server non contiene un'intestazione HTTP <code>mime-type</code>. Per ovviare a questo problema, è possibile utilizzare un metodo aggiuntive per sovrascrivere l'header inviato dal server, nel caso non sia presente o non sia impostato a <code>text/xml</code>.</p>
<pre>http_request = new XMLHttpRequest();
http_request.overrideMimeType('text/xml');
</pre>
<p>Dopodichè occorre decidere cosa fare con la risposta inviata dal server. Quindi bisogna dire all'oggetto XMLHttpRequest quale funzione JavaScript elaborerà il codice XML. Questo si fa impostando la proprietà <code>onreadystatechange</code> dell'oggetto con il nome della funzione JavaScript, in questo modo:</p>
<p><code>http_request.onreadystatechange = nomeFunzione;</code></p>
<p>Si noti che non ci sono parentesi dopo il nome della funzione e non viene passato alcun parametro, perchè si sta semplicemente assegnando un riferimento alla funzione, non la si sta ancora chiamando. Inoltre, invece di passare il nome di una funzione, si potrebbe utilizzare la tecnica JavaScript di definire funzioni "al volo" e di definire le azioni che elaboreranno la risposta XML, in questo modo:</p>
<pre>http_request.onreadystatechange = function(){
// azioni da eseguire...
};
</pre>
<p>Dopo aver dichiarato ciò che accadrà quando si riceverà la risposta dal server, occorre inviare la richiesta. Bisogna chiamare i metodi <code>open()</code> e <code>send()</code> della classe che esegue le richieste, in questo modo:</p>
<pre>http_request.open('GET', 'http://www.esempio.org/qualsiasi.file', true);
http_request.send(null);
</pre>
<ul>
<li>Il primo parametro da passare a <code>open()</code> è il metodo che si desidera utilizzare per la richiesta HTTP: GET, POST, HEAD o qualsiasi altro metodo che si desideri utilizzare e sia supportato dal server. Il metodo deve essere scritto in lettere MAIUSCOLE, come specificato dallo standard HTTP; altrimenti alcuni browser (come Firefox) potrebbero non eseguire la richiesta. Per ulteriori informazioni sui possibili metodi da utilizzare si veda le: <a class="external" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html">specifiche del W3C</a></li>
<li>Il secondo parametro è l'URL della pagina che si sta richiedendo. Per ragioni di sicurezza, non è possibile chiamare pagine che si trovino su un dominio differente da quello in cui si trova la pagina corrente. Bisogna anche assicurarsi di utilizzare esattamente lo stesso dominio in tutte le pagine o si avrà un errore di 'permission denied' quando si chiama il metodo <code>open()</code>. Un errore comune è quello di accedere al sito da <tt>dominio.org</tt> e cercare poi di chiamare pagine che si trovano su <tt>www.dominio.org</tt></li>
<li>Il terzo parametro specifica se la richiesta deve essere asincrona. Se è impostato a <code>TRUE</code> (e di solito è così), la funzione JavaScript resterà in esecuzione anche prima dell'arrivo della risposta.</li>
</ul>
<p>Il parametro del metodo <code>send()</code> è costituito dai dati che si vogliono inviare al server se la richiesta è di tipo <code>POST</code>. I dati vengono passati sotto forma di querystring, così:</p>
<p><code>nome1=valore1&nome2=valore2&ecc=ecc</code></p>
<p>Si noti che se si desidera inviare i dati come <code>POST</code>, occorre modificare il tipo MIME della richiesta con la riga seguente:</p>
<pre>http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
</pre>
<p>In caso contrario, il server ignorerà la richiesta.</p>
<h3 id="Step_2_.E2.80.93_.22Via.21.22_o_Come_gestire_la_risposta_del_server" name="Step_2_.E2.80.93_.22Via.21.22_o_Come_gestire_la_risposta_del_server">Step 2 – "Via!" o Come gestire la risposta del server</h3>
<p>Come si è detto, all'atto di inviare la richiesta, si è fornito il nome della funzione JavaScript che deve elaborare la risposta.</p>
<p><code>http_request.onreadystatechange = nomeFunzione;</code></p>
<p>Ma cosa dovrebbe fare questa funzione? Primo, la funzione deve controllare lo stato della richiesta. Se lo stato ha un valore di 4, significa che la risposta è stata ricevuta per intero e si può continuare l'elaborazione:</p>
<p> </p>
<pre>if (http_request.readyState == 4) {
// tutto a posto, la risposta è stata ricevuta
} else {
// non sono ancora pronto
}
</pre>
<p>Ecco la lista completa dei possibili valori di <code>readyState</code>:</p>
<ul>
<li>0 (non inizializzato)</li>
<li>1 (sta caricando)</li>
<li>2 (già caricato)</li>
<li>3 (interattivo)</li>
<li>4 (completato)</li>
</ul>
<p>(<a class="external" href="http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/readystate_1.asp">Fonte</a>) (1)</p>
<p>Bisognerà poi controllare il codice di stato della risposta HTTP. Tutti i codici possibili sono elencati nel <a class="external" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">sito del W3C</a>. Per i nostri scopi, ci interessa soltanto il codice <code>200 OK</code>.</p>
<pre>if (http_request.status == 200) {
// perfetto!
} else {
// c'è stato un problema nella richiesta,
// per esempio un codice di errore 404 (Not Found)
// o 500 (Internal Server Error)
}
</pre>
<p>Una volta controllati lo stato della richiesta e il codice di stato HTTP della risposta, sarà lo sviluppatore a decidere cosa desidera fare con i dati ricevuti dal server. Per accedere ad essi, vi sono due possibilità:</p>
<ul>
<li><code>http_request.responseText</code> – restituisce la risposta sotto forma di stringa di testo</li>
<li><code>http_request.responseXML</code> – restituisce la risposta sotto forma di oggetto <code>XMLDocument</code> che si può navigare tramite le funzioni DOM.</li>
</ul>
<h3 id="Passo_3_-_.22Tutti_insieme_ora.21.22.2C_Un_semplice_esempio" name="Passo_3_-_.22Tutti_insieme_ora.21.22.2C_Un_semplice_esempio">Passo 3 - "Tutti insieme ora!", Un semplice esempio</h3>
<p>Vediamo ora tutti gli elementi esaminati finora combinati insieme. Il seguente JavaScript richiede un documento HTML (<code>test.html</code>), che contiene il testo "Sono un test.", e farà un <code>alert()</code> coi contenuti di questo file.</p>
<pre><script type="text/javascript" language="javascript">
function eseguiRichiesta(url) {
var http_request = false;
if (window.XMLHttpRequest) { // Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
// Vedi note sotto
}
} else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Giving up :( Non riesco a creare una istanza XMLHTTP');
return false;
}
http_request.onreadystatechange = function() { alertContents(http_request); };
http_request.open('GET', url, true);
http_request.send(null);
}
function alertContents(http_request) {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
alert(http_request.responseText);
} else {
alert('Si è verificato un problema con la richiesta');
}
}
}
</script>
<span
style="cursor: pointer; text-decoration: underline"
onclick="eseguiRichiesta('test.html')">
Fai una richiesta
</span>
</pre>
<p>In questo esempio:</p>
<ul>
<li>L'utente clicca sul link "Fai una richiesta";</li>
<li>Viene chiamata la funzione <code>eseguiRichiesta()</code> con un parametro: il nome del file <code>test.html</code>, che si trova nella stessa directory;</li>
<li>Il browser esegue la richiesta e l'esecuzione passa a <code>alertContents()</code>;</li>
<li><code>alertContents()</code> controlla se l'esecuzione è stata ricevuta e se lo stato della risposta è OK: in caso affermativo chiama un <code>alert()</code> con i contenuti del file <code>test.html</code>.</li>
</ul>
<p>Si può provare questo esempio <a class="external" href="http://www.w3clubs.com/mozdev/httprequest_test.html">qui</a> e si può leggere il file "test.html" <a class="external" href="http://www.w3clubs.com/mozdev/test.html">qui</a>.</p>
<p><b>Nota</b>: La riga di codice <code> http_request.overrideMimeType('text/xml');</code> causa degli errori nella Console JavaScript di Firefox 1.5 o superiore nel caso che la pagina chiamata non sia costituita da XML ben formato (come in questo caso). Questo comportamento è corretto ed è documentato qui: <a class="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=311724" rel="freelink">https://bugzilla.mozilla.org/show_bug.cgi?id=311724</a> - l'articolo verrà rivisto per correggere questo errore.</p>
<p><b>Nota 2</b>: se si invia una richiesta con una porzione di codice che restituisce XML e non un file XML statico, bisogna impostare alcune intestazioni nella risposta perchè la pagina funzioni anche su Internet Explorer. Se non si imposta l'intestazione <code>Content-Type: application/xml</code>, IE lancia un errore JavaScript 'Object Expected' appena si cerca di accedere a un elemento XML. Se non si imposta l'intestazione <code>Cache-Control: no-cache</code>, il browser registra la risposta nella cache e non rieseguirà più la richiesta, il che fa impazzire molti sviluppatori in fase di debugging.</p>
<p><b>Nota 3</b>: se la variabile <code>http_request</code> è globale, se vi sono altre funzioni che chiamano <code>makeRequest()</code>, possono sovrasciversi a vicenda. Per evitare questo problema, occorre dichiarare questa variabile come locale e passarla alla funzione <code>alertContent()</code>.</p>
<p><b>Nota 4</b>: nel registrare la funzione callback per <code>onreadystatechange</code> non è possibile passare alcun argomento:</p>
<pre>http_request.onreadystatechange = function() { alertContents(http_request); }; //1 (richiesta simultanea)
http_request.onreadystatechange = alertContents(http_request); //2 (non funziona)
http_request.onreadystatechange = alertContents; //3 (variabile globale)
</pre>
<p>Il metodo 1 permette di elaborare diverse richieste simultaneamente. Il metodo 2 non funziona. Il metodo 3 è da utilizzare se <code>http_request</code> è una variabile globale.</p>
<h3 id="Passo_4_-_.22Gli_X-Files.22.2C_o_Elaborare_la_risposta_XML" name="Passo_4_-_.22Gli_X-Files.22.2C_o_Elaborare_la_risposta_XML">Passo 4 - "Gli X-Files", o Elaborare la risposta XML</h3>
<p>Nell'esempio precedente, dopo che la risposta HTTP è stata ricevuta si è utilizzata la proprietà <code>reponseText</code> dell'oggetto richiesta, che conteneva i contenuti del file <tt>test.html</tt>. Proveremo ora a utilizzare la proprietà <code>responseXML</code>.</p>
<p>Prima di tutto, occorre creare un documento XML valido che verrà chiamato in seguito. Il documento (<tt>test.xml</tt>) contiene quanto segue:</p>
<pre><?xml version="1.0" ?>
<root>
Sono un test.
</root>
</pre>
<p>Nello script occorre cambiare soltanto la riga seguente:</p>
<pre>...
onclick="eseguiRichiesta('test.xml')">
...
</pre>
<p>In <code>alertContents()</code>, bisogna poi sostituire la riga <code>alert(http_request.responseText);</code> con:</p>
<pre>var xmldoc = http_request.responseXML;
var root_node = xmldoc.getElementsByTagName('root').item(0);
alert(root_node.firstChild.data);
</pre>
<p>Questo codice prende l'oggetto <code>XMLDocument</code> fornito da <code>responseXML</code> e utilizza i metodi DOM per accedere ai dati contenuti nel documento XML. Si può vedere <code>test.xml</code> <a class="external" href="http://www.w3clubs.com/mozdev/test.xml">qui</a>. Si può vedere in azione questa versione dello script <a class="external" href="http://www.w3clubs.com/mozdev/httprequest_test_xml.html">qui</a>.</p>
<p>Per ulteriori dettagli sui metodi DOM, si vedano i documenti sull'<a class="external" href="http://www.mozilla.org/docs/dom/">Implementazione DOM di Mozilla</a>.</p>
<hr>
<p><small>La bozza di standard del W3C indica i seguenti valori per la proprietà <code>readystate</code>: </small></p>
<ul>
<li>0 Non inizializzato: il valore iniziale</li>
<li>1 Aperto: il metodo open() è stato chiamato con successo</li>
<li>2 Inviato: il browser a completato la richiesta con successo, ma ancora non ha ricevuto alcun dato in risposta</li>
<li>3 Ricezione: immediatamente prima di ricevere il corpo del documento (se esiste). Tutte le intestazioni HTTP sono state ricevute (la bozza pone però un quesito: come comportarsi con le richieste di tipo HEAD?)</li>
<li>4 Caricato: il trasferimento dei dati è stato completato</li>
</ul>
<p><a class="external" href="http://www.w3.org/TR/2006/WD-XMLHttpRequest-20060405/#xmlhttprequest">Fonte</a></p>
<p>{{ languages( { "ca": "ca/AJAX/Primers_passos", "de": "de/AJAX/Getting_Started", "en": "en/AJAX/Getting_Started", "es": "es/AJAX/Primeros_Pasos", "fr": "fr/AJAX/Premiers_pas", "ja": "ja/AJAX/Getting_Started", "pl": "pl/AJAX/Na_pocz\u0105tek", "pt": "pt/AJAX/Como_come\u00e7ar" } ) }}</p>
|