Come configurare smartphone e PC. Portale informativo

Invio di richieste POST tramite JavaScript. Recupero dati XML

Il sogno per cui è stato creato il Web è comune spazio informativo in cui comunichiamo condividendo informazioni. La sua versatilità ne è parte integrante: un collegamento ipertestuale può portare ovunque, sia che si tratti di informazioni personali, locali o globali, di bozze o di testi rivisti.

Tim Bernes-Lee, Il World Wide Web: una storia personale molto breve

Protocollo

Se digiti eloquentjavascript.net/17_http.html nella barra degli indirizzi del tuo browser, il browser prima riconosce l'indirizzo del server associato al nome eloquentjavascript.net e prova ad aprire Connessione TCP sulla porta 80 - la porta predefinita per HTTP. Se il server esiste e accetta la connessione, il browser invia qualcosa del tipo:

GET /17_http.html HTTP / 1.1
Host: eloquentjavascript.net
Agente utente: nome del browser

Il server risponde sulla stessa connessione:

HTTP / 1.1 200 OK
Lunghezza contenuto: 65585
Tipo di contenuto: testo / html


...il resto del documento

Il browser prende la parte che segue la risposta dopo riga vuota e lo visualizza come documento HTML.

L'informazione inviata dal cliente è chiamata richiesta. Inizia con la riga:

GET /17_http.html HTTP / 1.1

La prima parola è il metodo di richiesta. GET significa che dobbiamo ottenere una risorsa specifica. Altri metodi comuni sono DELETE per l'eliminazione, PUT per la sostituzione e POST per l'invio di informazioni. Nota che il server non è tenuto a soddisfare ogni richiesta che riceve. Se scegli un sito a caso e digli ELIMINA home page- molto probabilmente rifiuterà.

La parte dopo il nome del metodo è il percorso della risorsa a cui è stata inviata la richiesta. Nel caso più semplice, una risorsa è solo un file sul server, ma il protocollo non si limita a questa capacità. Una risorsa può essere qualsiasi cosa che può essere passata come file. Molti server creano risposte al volo. Ad esempio, se apri twitter.com/marijnjh, il server cercherà nel database l'utente marijnjh e, se lo trova, creerà una pagina del profilo per quell'utente.

Dopo il percorso della risorsa, la prima riga della richiesta cita HTTP/1.1 per indicare la versione del protocollo HTTP che sta utilizzando.

Anche la risposta del server inizia con la versione del protocollo seguita dallo stato della risposta: prima il codice da tre cifre, quindi una riga.

HTTP / 1.1 200 OK

I codici di stato che iniziano con 2 indicano le richieste riuscite. I codici che iniziano con 4 significano che qualcosa è andato storto. 404 è lo stato HTTP più famoso, che indica che la risorsa richiesta non è stata trovata. I codici che iniziano con 5 indicano che si è verificato un errore sul server, ma non dovuto alla richiesta.

La prima riga di una richiesta o di una risposta può essere seguita da un numero qualsiasi di righe di intestazione. Questi sono i nomi: stringhe di valore che rappresentano Informazioni aggiuntive su una richiesta o una risposta. Queste intestazioni sono state incluse nell'esempio:

Lunghezza contenuto: 65585
Tipo di contenuto: testo / html
Ultima modifica: Mer, 09 Apr 2014 10:48:09 GMT

Ciò determina la dimensione e il tipo del documento ricevuto in risposta. V in questo casoè un documento HTML di 65'585 byte. Indica anche quando il documento è stato modificato l'ultima volta.

Per la maggior parte, il client o il server determina quali intestazioni includere in una richiesta o risposta, sebbene alcune intestazioni siano necessarie. Ad esempio, Host, che denota un nome host, dovrebbe essere incluso nella richiesta, perché un server può servire molti nomi host su un indirizzo IP e senza questa intestazione il server non saprà con quale host il client sta cercando di comunicare.

Dopo le intestazioni, sia la richiesta che la risposta possono specificare una stringa vuota, seguita da un corpo contenente i dati da trasferire. Le richieste GET e DELETE non inviano dati aggiuntivi, ma PUT e POST lo fanno. Alcune risposte, come i messaggi di errore, non richiedono un corpo.

Browser e HTTP

Come abbiamo visto nell'esempio, il browser effettua una richiesta quando inseriamo l'URL in barra degli indirizzi... Quando ricevuto documento HTML contiene riferimenti ad altri file, come immagini o File JavaScript, vengono richiesti anche al server.

Un sito web medio può contenere facilmente da 10 a 200 risorse. Per poterli richiedere più velocemente, i browser effettuano più richieste contemporaneamente, invece di aspettare che le richieste finiscano una per una. Tali documenti vengono sempre richiesti tramite richieste GET.

Sul Pagine HTML potrebbero esserci moduli che consentono agli utenti di inserire informazioni e inviarle al server. Ecco un esempio di modulo:

Nome:

Messaggio:

Il codice descrive un modulo con due campi: uno piccolo richiede un nome e uno grande per un messaggio. Quando fai clic sul pulsante "Invia", le informazioni di questi campi verranno codificate in una stringa di query. Quando l'attributo del metodo dell'elemento è GET, o quando non è affatto specificato, la stringa di query viene inserita nell'URL dal campo dell'azione e il browser effettua una richiesta GET con quell'URL.

GET /example/message.html?name=Jean&message=Yes%3F HTTP / 1.1

L'inizio della stringa di query è indicato da un punto interrogativo. Questo è seguito da coppie di nomi e valori corrispondenti a attributo del nome campi del modulo e il contenuto di tali campi. La e commerciale (&) viene utilizzata per separarli.

Il messaggio inviato nell'esempio contiene la stringa “Sì?”, anche se il punto interrogativo è stato sostituito con uno strano codice. È necessario eseguire l'escape di alcuni caratteri nella stringa di query. Il punto interrogativo è incluso, ed è rappresentato dal codice% 3F. C'è una regola non scritta secondo cui ogni formato deve avere un modo per sfuggire ai caratteri. Questa regola si chiama codifica dell'URL utilizza una percentuale seguita da due cifre esadecimali per rappresentare il codice carattere. 3F decimale sarebbe 63, che è il codice del punto interrogativo. JavaScript ha le funzioni encodeURIComponent e decodeURIComponent per la codifica e la decodifica.

Console.log (encodeURIComponent ("Ciao e arrivederci")); // → Hello% 20% 26% 20goodbye console.log (decodeURIComponent ("Hello% 20% 26% 20goodbye")); // → Ciao e arrivederci

Se cambiamo l'attributo del metodo sul modulo nell'esempio precedente in POST, richiesta HTTP l'invio del modulo sarà effettuato con Metodo POST che invierà la stringa di query nel corpo della richiesta invece di aggiungerla all'URL.

POST /esempio/messaggio.html HTTP / 1.1
Lunghezza del contenuto: 24
Tipo di contenuto: application / x-www-form-urlencoded

Nome = Jean & messaggio = Sì% 3F

Previo accordo Metodo GET utilizzato per query che non hanno effetti collaterali, come le ricerche. Le richieste che cambiano qualcosa sul server creano nuovo account o inviare un messaggio, deve essere inviato con il metodo POST. Programmi client come un browser, sanno che non è necessario effettuare richieste POST in questo modo e talvolta effettuano richieste GET senza che l'utente se ne accorga, ad esempio per scaricare in anticipo i contenuti di cui l'utente potrebbe presto aver bisogno.

Nel prossimo capitolo, torneremo ai form e parleremo di come possiamo crearli con JavaScript.

XMLHttpRequest

L'interfaccia attraverso la quale JavaScript nel browser può effettuare richieste HTTP si chiama XMLHttpRequest (notare come saltano le dimensioni delle lettere). È stato sviluppato da Microsoft per il browser Internet Explorer alla fine degli anni '90. A quel tempo formato XML era molto popolare nel mondo del software aziendale - e in questo mondo Microsoft si è sempre sentita a casa. Era così popolare che l'acronimo XML veniva bloccato davanti all'interfaccia per lavorare con HTTP, sebbene quest'ultimo non fosse affatto associato a XML.

Eppure il nome non è del tutto privo di significato. L'interfaccia consente di analizzare le risposte come se fossero documenti XML. Mescolare due cose diverse (richiesta e analisi della risposta) in una è, ovviamente, un progetto disgustoso, ma cosa puoi fare.

Quando l'interfaccia XMLHttpRequest è stata aggiunta a Internet Explorer, è diventato possibile fare cose che in precedenza erano molto difficili da fare. Ad esempio, i siti hanno iniziato a mostrare elenchi di suggerimenti mentre l'utente digita qualcosa in un campo di testo. Lo script invia il testo al server su HTTP mentre l'utente sta digitando. Un server che dispone di un database per possibili opzioni input, cerca tra le voci quelle corrispondenti e le restituisce per la visualizzazione. Sembrava molto bello: le persone aspettavano che l'intera pagina si ricaricasse dopo ogni interazione con il sito.

Altro browser importante del tempo Mozilla (poi Firefox) non voleva restare indietro. Per consentire cose simili, Mozilla ha copiato l'interfaccia insieme al nome. La prossima generazione di browser ha seguito l'esempio e oggi XMLHttpRequest è lo standard de facto.

Invio di una richiesta

Per inviare una semplice richiesta, creiamo un oggetto request con un costruttore XMLHttpRequest e chiamiamo i metodi open e send.

Var req = new XMLHttpRequest (); req.open ("GET", "example / data.txt", false); req.send (null); console.log (req.responseText); // → Questo è il contenuto di data.txt

Il metodo aperto imposta la richiesta. Nel nostro caso, abbiamo deciso di fare una richiesta GET per il file example / data.txt. Gli URL che non iniziano con un nome di protocollo (ad esempio, http :) sono chiamati relativi, cioè sono interpretati relativamente documento corrente... Quando iniziano con una barra (/), sostituiscono il percorso corrente, la parte dopo il nome del server. Altrimenti, parte percorso attuale fino all'ultima barra viene posta prima dell'URL relativo.

Dopo aver aperto la richiesta, possiamo inviarla utilizzando il metodo di invio. L'argomento è il corpo della richiesta. Per le richieste GET, viene utilizzato null. Se il terzo argomento da aprire era falso, send ritornerà solo dopo che è stata ricevuta la risposta alla nostra richiesta. Per ottenere il corpo della risposta, possiamo leggere la proprietà responseText dell'oggetto richiesta.

Puoi anche ottenere altre informazioni dall'oggetto risposta. Il codice di stato è disponibile nella proprietà status e il testo di stato è disponibile in statusText. Le intestazioni possono essere lette da getResponseHeader.

Var req = new XMLHttpRequest (); req.open ("GET", "example / data.txt", false); req.send (null); console.log (req.status, req.statusText); // → 200 OK console.log (req.getResponseHeader ("tipo di contenuto")); // → testo / semplice

I nomi delle intestazioni non fanno distinzione tra maiuscole e minuscole. Di solito sono scritti con lettera maiuscola all'inizio di ogni parola, ad esempio "Content-Type", ma "content-type" o "conTeNt-TyPe" descriveranno la stessa intestazione.

Il browser aggiungerà da solo alcune intestazioni, come "Host" e altre, di cui il server ha bisogno per calcolare la dimensione del corpo. Ma puoi aggiungere le tue intestazioni con il metodo setRequestHeader. Questo è necessario per casi speciali e richiede l'assistenza del server a cui stai accedendo: è libero di ignorare le intestazioni che non può gestire.

Richieste asincrone

Nell'esempio, la richiesta è stata completata al termine della chiamata da inviare. Questo è conveniente perché proprietà come responseText sono immediatamente disponibili. Ma questo significa che il nostro programma attenderà che il browser e il server comunichino tra loro. A cattiva connessione, un server debole, oppure file grande questo potrebbe richiedere a lungo... Questo è anche un male perché nessun gestore di eventi verrà attivato mentre il programma è in modalità standby: il documento smetterà di rispondere alle azioni dell'utente.

Se passiamo true come terzo argomento da aprire, la richiesta sarà asincrona. Ciò significa che quando si chiama send, la richiesta viene messa in coda per l'invio. Il programma continua a funzionare e il browser si occupa di inviare e ricevere dati in background.

Ma durante l'elaborazione della richiesta, non riceveremo risposta. Abbiamo bisogno di un meccanismo per notificare che i dati sono arrivati ​​e sono pronti. Per fare ciò, dovremo ascoltare l'evento "load".

Var req = new XMLHttpRequest (); req.open ("GET", "example / data.txt", true); req.addEventListener ("load", function () (console.log ("Fatto:", req.status);)); req.send (null);

Proprio come la chiamata a requestAnimationFrame nel Capitolo 15, questo codice ci costringe a usare lo stile di programmazione asincrona racchiudendo il codice che dovrebbe essere eseguito dopo la richiesta in una funzione e organizzando la chiamata a questa funzione in Il momento giusto... Torneremo su questo più tardi.

Recupero dati XML

Quando la risorsa restituita dall'oggetto XMLHttpRequest è un documento XML, la proprietà responseXML conterrà la vista analizzata del documento. Funziona in modo simile al DOM, tranne per il fatto che manca della funzionalità intrinseca dell'HTML come la proprietà style. L'oggetto contenuto in responseXML corrisponde all'oggetto documento. La sua proprietà documentElement fa riferimento al tag esterno di un documento XML. V prossimo documento(esempio / fruit.xml) questo tag sarebbe:

Possiamo ottenere un file come questo:

Var req = new XMLHttpRequest (); req.open ("GET", "esempio / fruit.xml", false); req.send (null); console.log (req.responseXML.querySelectorAll ("frutto"). length); // → 3

I documenti XML possono essere utilizzati per lo scambio con il server informazioni strutturate... La loro forma - tag nidificati - è adatta per memorizzare la maggior parte dei dati, bene, o per almeno meglio di file di testo... L'interfaccia DOM è scomoda in termini di recupero delle informazioni e Documenti XML sono abbastanza prolissi. Di solito è meglio comunicare utilizzando i dati JSON, che sono più facili da leggere e scrivere, sia per i programmi che per gli umani.

Var req = new XMLHttpRequest (); req.open ("GET", "esempio /fruit.json", false); req.send (null); console.log (JSON.parse (req.responseText)); // → (banana: "giallo", limone: "giallo", ciliegia: "rosso")

Sandbox per HTTP

Le richieste HTTP da una pagina Web sollevano problemi di sicurezza. La persona che controlla lo script può avere interessi diversi da quelli dell'utente sul cui computer è in esecuzione. In particolare, se vado su themafia.org, non voglio che i loro script siano in grado di interrogare mybank.com utilizzando le informazioni del mio browser come identificatore e mi istruisca a inviare tutti i miei soldi a un conto mafioso.

I siti Web possono difendersi da tali attacchi, ma richiede un certo sforzo e molti siti non riescono a farvi fronte. Per questo motivo, i browser li proteggono impedendo agli script di effettuare richieste ad altri domini (nomi come themafia.org e mybank.com).

Ciò può interferire con lo sviluppo di sistemi che necessitano di accesso a diversi domini per una buona ragione. Fortunatamente, il server può includere la seguente intestazione nella risposta, indicando ai browser che la richiesta potrebbe provenire da altri domini:

Accesso-Controllo-Consenti-Origine: *

Richieste di astrazione

Capitolo 10 nella nostra implementazione sistema modulare AMD abbiamo utilizzato l'ipotetica funzione backgroundReadFile. Ha preso un nome di file e una funzione e ha chiamato quella funzione dopo aver letto il contenuto del file. Qui implementazione semplice questa funzione:

Funzione backgroundReadFile (url, callback) (var req = new XMLHttpRequest (); req.open ("GET", url, true); req.addEventListener ("load", function () (if (req.status< 400) callback(req.responseText); }); req.send(null); }

Una semplice astrazione semplifica l'uso di XMLHttpRequest per semplici richieste GET. Se stai scrivendo un programma che effettua richieste HTTP, è una buona idea utilizzare una funzione di supporto in modo da non dover ripetere continuamente il brutto modello XMLHttpRequest.

L'argomento callback è un termine spesso usato per descrivere tali funzioni. La funzione di callback viene passata ad altro codice in modo che possa richiamarci in seguito.

Non è difficile scrivere la propria funzione di supporto HTTP su misura per il proprio programma. Il precedente effettua solo richieste GET e non ci dà il controllo sulle intestazioni o sul corpo della richiesta. Puoi scrivere un'altra variante per la richiesta POST o una più generale che supporti richieste diverse. Molte librerie JavaScript offrono wrapper per XMLHttpRequest.

Il problema principale con il wrapper di cui sopra è la gestione degli errori. Quando una richiesta restituisce un codice di stato di errore (400 o superiore), non fa nulla. Questo va bene in alcuni casi, ma immaginiamo di inserire un indicatore di caricamento sulla pagina per indicare che stiamo ricevendo informazioni. Se la richiesta fallisce perché il server è andato in crash o la connessione è interrotta, la pagina fingerà di essere occupata con qualcosa. L'utente aspetterà un po', poi si annoierà e deciderà che il sito è una specie di stupido.

Abbiamo bisogno di un'opzione in cui riceviamo un avviso di richiesta non riuscita in modo da poter agire. Ad esempio, possiamo rimuovere il messaggio di download e informare l'utente che qualcosa è andato storto.

La gestione degli errori nel codice asincrono è ancora più difficile che nel codice sincrono. Poiché spesso dobbiamo separare parte del lavoro e inserirlo in una funzione di callback, l'ambito del blocco try è privo di significato. Nel codice seguente, l'eccezione non verrà rilevata perché la chiamata a backgroundReadFile viene restituita immediatamente. Quindi il controllo lascia il blocco try e la funzione da esso non verrà chiamata.

Try (backgroundReadFile ("example / data.txt", function (text) (if (text! = "Expected") throw new Error ("Era inaspettato");));) catch (e) (console.log ( "Ciao dal blocco catch");)

Per elaborare le richieste non andate a buon fine, dovrai inviare funzione aggiuntiva nel nostro wrapper, e chiamarlo in caso di problemi. Un'altra opzione consiste nell'usare la convenzione secondo cui se la richiesta fallisce, viene passato un argomento aggiuntivo alla funzione di callback che descrive il problema. Esempio:

Funzione getURL (url, callback) (var req = new XMLHttpRequest (); req.open ("GET", url, true); req.addEventListener ("load", function () (if (req.status< 400) callback(req.responseText); else callback(null, new Error("Request failed: " + req.statusText)); }); req.addEventListener("error", function() { callback(null, new Error("Network error")); }); req.send(null); }

Il codice che utilizza getURL dovrebbe verificare se è stato restituito un errore e gestirlo se ce n'è uno.

GetURL ("data / nonsense.txt", function (content, error) (if (error! = Null) console.log ("Impossibile recuperare nonsense.txt:" + errore); else console.log ("nonsense.txt : "+ contenuto);));

Non aiuta con le eccezioni. Quando eseguiamo diverse azioni asincrone in successione, un'eccezione in qualsiasi punto della catena in ogni caso (a meno che non avvolga ciascun gestore nel proprio blocco try/catch) cadrà al livello più alto e interromperà l'intera catena.

promesse

È difficile scrivere codice asincrono per progetti complessi sotto forma di semplice richiamate... È molto facile dimenticare di controllare un errore o consentire a un'eccezione imprevista di interrompere bruscamente il programma. Inoltre, l'organizzazione elaborazione corretta errori e passare l'errore attraverso più callback successive è molto noioso.

Ci sono stati molti tentativi di risolvere questo problema con astrazioni aggiuntive. Uno dei tentativi di maggior successo si chiama promesse. Le promesse avvolgono un'azione asincrona in un oggetto che può essere passato e che deve fare qualcosa quando l'azione viene completata o non riesce. Tale interfaccia è già diventata parte della corrente Versioni JavaScript e per le versioni precedenti può essere utilizzato come libreria.

L'interfaccia delle promesse non è particolarmente intuitiva, ma potente. In questo capitolo lo descriveremo solo parzialmente. Maggiori informazioni può essere trovato su www.promisejs.org

Per creare l'oggetto promesse, chiamiamo il costruttore Promise, assegnandogli una funzione di inizializzazione dell'azione asincrona. Il costruttore chiama questa funzione e le passa due argomenti, che sono anch'essi funzioni. Il primo dovrebbe essere chiamato in caso di successo, l'altro in caso di fallimento.

Ed ecco il nostro wrapper per le richieste GET, che questa volta restituisce una promessa. Ora lo chiameremo semplicemente ottenere.

Funzione get (url) (return new Promise (function (success, fail) (var req = new XMLHttpRequest (); req.open ("GET", url, true); req.addEventListener ("load", function () ( if (req.status< 400) succeed(req.responseText); else fail(new Error("Request failed: " + req.statusText)); }); req.addEventListener("error", function() { fail(new Error("Network error")); }); req.send(null); }); }

Si noti che l'interfaccia della funzione stessa è stata semplificata. Le passiamo l'URL e lei restituisce la promessa. Funge da gestore per l'output della richiesta. Ha un metodo then che viene chiamato con due funzioni, una per gestire il successo e l'altra per gestire il fallimento.

Get ("esempio / data.txt") Quindi (funzione (testo) (console.log ("data.txt:" + testo);), funzione (errore) (console.log ("Impossibile recuperare data.txt : "+ errore);));

Mentre questo è ancora uno dei modi per esprimere ciò che abbiamo già fatto. È solo quando hai una catena di eventi che vedi una differenza notevole.

La chiamata quindi produce una nuova promessa il cui risultato (il valore passato ai gestori di successo) dipende dal valore di ritorno della prima funzione a cui abbiamo passato. Questa funzione può restituire un'altra promessa, indicando che è in corso un lavoro asincrono aggiuntivo. In questo caso, la promessa restituita da allora stessa attenderà la promessa restituita dalla funzione del gestore e si verificherà un esito positivo o negativo con lo stesso valore. Quando la funzione del gestore restituisce un valore non promesso, la promessa restituita ha successo utilizzando tale valore come risultato.

Ciò significa che puoi utilizzare quindi per modificare il risultato di una promessa. Per esempio, funzione successiva restituisce una promessa il cui risultato è il contenuto dell'URL specificato analizzato come JSON:

Funzione getJSON (url) (return get (url) .then (JSON.parse);)

L'ultima chiamata quindi non ha designato un gestore di errori. Questo è permesso. L'errore verrà passato alla promessa restituita fino a quel momento, e questo è ciò di cui abbiamo bisogno: getJSON non sa cosa fare quando qualcosa va storto, ma c'è la speranza che il codice chiamante lo sappia.

Come esempio che mostra l'uso delle promesse, scriveremo un programma che riceve un numero di file JSON dal server e visualizza la parola "download" durante l'esecuzione della richiesta. I file contengono informazioni su persone e collegamenti ad altri file con informazioni su altre persone in proprietà come padre, madre, coniuge.

Dobbiamo ottenere il nome della madre del coniuge da example / bert.json. In caso di problemi, è necessario rimuovere il testo "caricamento" e visualizzare un messaggio di errore. Ecco come puoi farlo con le promesse:

Il programma risultante è relativamente compatto e leggibile. Il metodo catch è simile a then, ma prevede solo un gestore di risultati non riuscito e, in caso di successo, passa il risultato invariato. L'esecuzione del programma continuerà nel modo consueto dopo aver catturato l'eccezione, proprio come nel caso di try/catch. Pertanto, il final then, che rimuove il messaggio di caricamento, viene eseguito comunque, anche se fallisce.

Si potrebbe pensare all'interfaccia della promessa come a un linguaggio separato per gestire l'esecuzione del programma in modo asincrono. Le chiamate aggiuntive a metodi e funzioni necessarie per farlo funzionare fanno sembrare il codice un po' strano, ma non così scomodo come gestire tutti gli errori manualmente.

Apprezzo HTTP

Quando si crea un sistema in cui un programma JavaScript in un browser (lato client) comunica con programma server, è possibile utilizzare diverse opzioni per modellare tale comunicazione.

Una tecnica comune sono le chiamate di procedura remota. In questo modello, la comunicazione segue lo schema delle normali chiamate di funzione, solo queste funzioni vengono eseguite su un altro computer. La chiamata serve a creare una richiesta al server, che include il nome della funzione e gli argomenti. La risposta alla richiesta include un valore restituito.

Quando si utilizzano chiamate di procedura remota, HTTP funge solo da trasporto per la comunicazione e molto probabilmente si scriverà un livello di astrazione che lo nasconde completamente.

Un altro approccio consiste nel costruire il proprio sistema di comunicazione attorno al concetto di risorse e metodi HTTP. Invece di una chiamata di procedura remota chiamata addUser, lo fai PUT richiesta a / utenti / larry. Invece di codificare le proprietà personalizzate negli argomenti della funzione, definisci il formato del documento o usi formato esistente che rappresenterà l'utente. Il corpo della richiesta PUT che fa nuova risorsa, sarà semplicemente un documento di questo formato. Una risorsa si ottiene tramite una richiesta GET al suo URL (/user/larry), che restituisce un documento che rappresenta la risorsa.

Il secondo approccio semplifica l'uso di alcuni Funzionalità HTTP, ad esempio, supporto per la memorizzazione nella cache delle risorse (una copia della risorsa viene archiviata sul lato client). Aiuta anche a creare un'interfaccia coerente perché è più facile pensare in termini di risorse che in termini di funzioni.

Sicurezza e HTTPS

I dati viaggiano in Internet lungo un percorso lungo e pericoloso. Per arrivare a destinazione, hanno bisogno di saltare tutti i tipi di posti, che vanno da Reti Wi-Fi caffetterie alle catene controllate da diverse organizzazioni e stati. In qualsiasi punto del percorso, possono essere letti o addirittura modificati.

Se hai bisogno di mantenere segreto qualcosa, come le password delle email, o i dati devono arrivare a destinazione invariati, come il numero di conto bancario a cui stai trasferendo denaro, il semplice HTTP non è sufficiente.

Il protocollo HTTP sicuro, i cui URL iniziano con https: //, avvolge il traffico HTTP in un modo più difficile da leggere e modificare. Il client prima conferma che il server è chi afferma di essere richiedendo al server di presentare un certificato crittografico emesso da una parte autorevole che il browser riconosce. Quindi, tutti i dati che passano attraverso la connessione vengono crittografati per prevenire intercettazioni e alterazioni.

In questo modo, quando tutto funziona correttamente, HTTPS previene sia i casi in cui qualcuno finge di essere un altro sito Web con cui comunichi, sia i casi di intercettazione della tua comunicazione. Non è perfetto e ci sono già stati casi in cui HTTPS ha fallito a causa di certificati falsi o rubati o programmi non funzionanti. Tuttavia, è molto facile fare qualcosa di male con HTTP e craccare HTTPS richiede il tipo di sforzo che può essere esercitato solo da agenzie governative o organizzazioni criminali molto serie (e talvolta non ci sono differenze tra queste organizzazioni).

Risultato

In questo capitolo abbiamo visto che HTTP è un protocollo per l'accesso alle risorse su Internet. Il client invia una richiesta contenente un metodo (solitamente GET) e un percorso che identifica la risorsa. Il server decide cosa fare con la richiesta e risponde con un codice di stato e un corpo della risposta. Le richieste e le risposte possono contenere intestazioni che trasmettono informazioni aggiuntive.

I browser effettuano richieste GET per ottenere le risorse necessarie per il rendering della pagina. Una pagina può contenere moduli che consentono di inviare le informazioni immesse dall'utente in una richiesta generata dopo l'invio del modulo. Imparerai di più su questo nel prossimo capitolo.

L'interfaccia attraverso la quale JavaScript effettua le richieste HTTP dal browser si chiama XMLHttpRequest. Puoi ignorare il prefisso "XML" (ma devi comunque scriverlo). Può essere utilizzato in due modi: sincrono, che blocca tutto il lavoro fino alla fine della richiesta, e asincrono, che richiede l'installazione di un gestore di eventi per tenere traccia della fine della richiesta. In quasi tutti i casi è preferibile modo asincrono... La creazione della richiesta si presenta così:

Var req = new XMLHttpRequest (); req.open ("GET", "example / data.txt", true); req.addEventListener ("load", function () (console.log (req.statusCode);)); req.send (null);

La programmazione asincrona è complicata. Le promesse sono un'interfaccia che lo rende più semplice aiutando a instradare i messaggi di errore e le eccezioni al gestore corretto e astraendo alcuni degli elementi ripetitivi e soggetti a errori.

Esercizi

Negoziazione dei contenuti
Una delle cose che HTTP può fare di cui non abbiamo discusso è chiamata negoziazione del contenuto. L'intestazione Accept in una richiesta può essere utilizzata per indicare al server quali tipi di documenti il ​​client desidera ricevere. Molti server lo ignorano, ma quando il server conosce diversi modi per codificare la risorsa, può guardare l'intestazione e inviare quella preferita dal client.

L'URL eloquentjavascript.net/author è configurato per rispondere sia in testo normale che HTML o JSON a seconda della richiesta del client. Questi formati sono definiti dai tipi di contenuto standardizzati text/plain, text/html e application/json.

Invia una richiesta per ricevere tutti e tre i formati per questa risorsa. Utilizzare il metodo setRequestHeader dell'oggetto XMLHttpRequest per impostare l'intestazione Accept su uno dei tipi richiesti contenuto. Assicurati di impostare l'intestazione dopo l'apertura, ma prima dell'invio.

Infine, prova a richiedere contenuti come applicazione / arcobaleni + unicorni e guarda cosa succede.

In attesa di più promesse
Il costruttore Promise ha un metodo all che, quando riceve un array di promesse, restituisce una promessa che attende il completamento di tutte le promesse specificate nell'array. Quindi emette un risultato positivo e restituisce un array con i risultati. Se una delle promesse nell'array fallisce, fallisce anche la promessa condivisa (con il valore della promessa non riuscita dall'array).

Prova qualcosa del genere scrivendo la funzione all.

Nota che una volta che una promessa è completa (quando ha esito positivo o negativo), non può restituire un errore o un esito positivo e ulteriori chiamate di funzione vengono ignorate. Questo può rendere più facile gestire gli errori nella tua promessa.

Function all (promises) (return new Promise (function (success, fail) (// Il tuo codice.));) // Codice di verifica. all (). then (function (array) (console.log ("Questo dovrebbe essere:", array);)); function presto (val) (return new Promise (function (success) (setTimeout (function () (success (val);), Math.random () * 500);));) all (). then (function (array) ) (console.log ("Questo dovrebbe essere:", array);)); function fail() (return new Promise (function (success, fail) (fail (new Error ("bang"));));) all (). then (function (array) (console.log ("We get here non dovrebbe ");), function (error) (if (error.message! =" bang ") console.log (" Bummer imprevisto: ", errore);));

Per molto tempo, molti siti hanno pagine dinamiche, ovvero si aggiornano senza riavviarsi. Questo è ottenuto da chiamate al server tramite JavaScript, nella maggior parte dei casi, è Richieste POST e GET... E quasi sempre tali siti vengono utilizzati per questo Ajax... E non tutti sanno (purtroppo) che Ajax non è un linguaggio separato, ma solo una libreria JavaScript... Conclusione: L'Ajax è solo strada conveniente inviare richieste POST, ma tutto questo può essere fatto senza il suo aiuto. Qui come inviare richieste POST tramite JavaScript senza Ajax, spiegherò in questo articolo.

Ora risolveremo un problema classico: questa è la somma di due numeri specificati dall'utente. Cioè, contiamo dai campi di testo 2 numeri, inviarli al server, ottenere la risposta e visualizzarli nella pagina. E tutto questo senza ricaricare la pagina.

Iniziamo in modo semplice: scrivere codice PHP:

$ a = $ _POST ["a"];
$ b = $ _POST ["b"];
echo $ a + $ b;
?>

Tutto è elementare qui, quindi non lo commenterò nemmeno. E ora la parte più difficile è il lato client:










La somma è pari a:


Codice HTML Non commenterò perché è completamente trasparente. Ma a JavaScript Aggiungo un po', nonostante i commenti dettagliati. Innanzitutto, la funzione getXmlHttp()è versatile. Puoi tranquillamente copiarlo nei tuoi script. Il suo compito è restituire tale XMLHTTP per farlo funzionare in qualsiasi browser. Perché l'opzione più popolare è nuovo XMLHttpRequest() tuttavia non funziona, ad esempio in IE6... Anche altre opzioni non sono universali, quindi qui selezioniamo solo un'opzione funzionante per qualsiasi browser.

Ho anche scritto nei commenti su " lavoro asincrono ". C'è anche un'opzione sincrona. L'unica differenza è che in sincrono fino a quando non viene ricevuta una risposta dal server, il browser non funzionerà, si blocca. È difficile per me trovare un compito del genere dove è necessario, quindi ho immediatamente scritto opzione asincrona... Funziona come segue: noi inviamo una richiesta e aspettiamo una risposta, ma il browser non si blocca... E quando arriva la risposta ( xmlhttp.readyState == 4), quindi elaboriamo immediatamente la risposta. Questa è la versione asincrona del lavoro, è un po 'più complicata, ma dovrebbe essere utilizzata solo (ad eccezione di casi molto rari).

In questo modo Le richieste POST vengono inviate tramite JavaScript... Come potete vedere Ajax non ne avevamo affatto bisogno. E consiglio vivamente che se hai solo un paio di richieste per l'intero sito, non pensare nemmeno di usare questa ingombrante libreria, ma usa il materiale di questo articolo.

Una lezione in cui utilizzeremo esempi per creare semplici richieste AJAX asincrone al server. Useremo sia il metodo GET che il metodo POST come metodo per trasferire le richieste. Sul server, elaboreremo le richieste utilizzando script PHP.

Che cos'è una richiesta AJAX asincrona?

La tecnologia AJAX viene utilizzata principalmente per effettuare richieste asincrone al server. Una richiesta asincrona è una richiesta che viene eseguita in sfondo e non impedisce all'utente di interagire con la pagina.

Quando si invia una richiesta asincrona, il browser (pagina) non viene "congelato", ad es. con lei, come prima, puoi lavorare. Ma allora come fai a sapere quando arriverà una risposta dal server. Per determinarlo, è necessario monitorare la proprietà readyState del browser. Questa proprietà contiene un numero, dal cui valore si può giudicare a che punto è la richiesta. La tabella seguente riassume i valori di base della proprietà readyState e i loro stati corrispondenti.

Quelli. si scopre che abbiamo bisogno di monitorare quando il valore della proprietà readyState è uguale a 4. Ciò significa che la richiesta inviata ha ricevuto una risposta dal server. Il resto dei valori viene utilizzato raramente nella pratica e alcuni browser potrebbero non supportarli.

Per determinare in quale fase si trova una richiesta, è necessario utilizzare l'evento onreadystatechange dell'oggetto XMLHttpRequest. Quest'evento si verifica ogni volta che cambia il valore della proprietà readyState. Pertanto, nel gestore di questo evento (di una funzione senza nome o con nome), è possibile scrivere azioni che verificheranno se questa proprietà è uguale a 4 e, se lo è, ad esempio, visualizzerà la risposta del server sulla pagina.

Effettuare una richiesta AJAX asincrona (metodo GET)

Considera la creazione di un asincrono Richiesta AJAX per un esempio che, dopo aver caricato la pagina, saluterà l'utente e visualizzerà il suo indirizzo IP.

Per fare ciò, è necessario creare 2 file sul server in una directory:

  1. welcome.html - Pagina HTML che verrà mostrata all'utente. Nella stessa pagina inseriremo uno script che eseguirà tutto azioni necessarie per il lavoro AJAX lato client.
  2. processing.php - File PHP che elaborerà la richiesta sul lato server e formerà la risposta. Iniziamo lo sviluppo creando la struttura di base del file welcome.html.
Un esempio di funzionamento AJAX

Un esempio di funzionamento AJAX

Diamo un'occhiata alla sequenza di azioni che devono essere eseguite sul lato client (in codice JavaScript):

    Prepariamo i dati necessari per eseguire la richiesta sul server. Se non sono necessari dati per eseguire la query sul server, questa fase può essere saltata.

    Creiamo una variabile che conterrà un'istanza dell'oggetto XHR (XMLHttpRequest).

    Configuriamo la richiesta utilizzando il metodo open().

    Sono specificati i seguenti parametri:

    • Il metodo con cui la richiesta verrà inviata al server (GET, POST).
    • L'URL che gestirà la richiesta sul server.
    • Tipo di richiesta: sincrono (falso) o asincrono (vero).
    • Nome utente e password se richiesti.
  1. Sottoscrivi l'evento onreadystatechange dell'oggetto XHR e specifica il gestore come una funzione anonima o denominata. Successivamente, creeremo un codice all'interno di questa funzione che controllerà lo stato della risposta ed eseguirà determinate azioni sulla pagina. La risposta che proviene dal server è sempre nella proprietà responseText.

    Oltre a controllare il valore della proprietà readyState in base al numero 4, è possibile controllare il valore della proprietà status. Questa proprietà determina lo stato della richiesta. Se è 200, allora è tutto a posto. In caso contrario, si è verificato un errore (ad esempio, 404 - URL non trovato).

    Inviamo una richiesta al server utilizzando il metodo send().

    Se usiamo il metodo GET per inviare una richiesta, allora passiamo i dati nel parametro questo metodo non c'è bisogno. Vengono passati come parte dell'URL.

    Se utilizziamo il metodo POST per inviare una richiesta, i dati devono essere passati come parametro al metodo send(). Inoltre, prima di chiamare questo metodo, è necessario impostare l'intestazione Content-Type in modo che il server sappia in quale codifica è arrivata la richiesta e possa decrittografarla.

Contenuto dell'elemento di script:

// 2. Creare una richiesta variabile var request = new XMLHttpRequest (); // 3. Configurazione della richiesta request.open ("GET", "processing.php", true); // 4. Sottoscrivere l'evento onreadystatechange ed elaborarlo utilizzando la funzione anonima request.addEventListener ("readystatechange", function () (// se gli stati della richiesta sono 4 e lo stato della richiesta è 200 (OK) se ((request.readyState = = 4) && (request.status == 200)) (// ad esempio, visualizza l'oggetto XHR nella console del browser console.log (request); // e la risposta (testo) ricevuta dal server nella console di avviso .log (request.responseText) ; // recupera l'elemento c id = welcome var welcome = document.getElementById ("welcome"); // sostituisci il contenuto dell'elemento con la risposta dal server welcome.innerHTML = request.responseText ;))); // 5. Invio di una richiesta al server request.send ();

Di conseguenza, il file welcome.html avrà il seguente codice:

Un esempio di funzionamento AJAX

Un esempio di funzionamento AJAX

Sul server (usando php):

  1. Prendiamo i dati. Se i dati vengono inviati tramite il metodo GET, dall'array globale $ _GET ["nome"]. E se i dati vengono trasferiti utilizzando il metodo POST, quindi dall'array globale $ _POST ["nome"].
  2. Utilizzando questi dati, eseguiamo alcune azioni sul server. Di conseguenza, avremo qualche risposta. Facciamo eco.

Esecuzione di una richiesta AJAX asincrona (metodo POST)

Modifichiamo l'esempio sopra. Ora la richiesta AJAX al server verrà eseguita dopo aver fatto clic sul pulsante. Riceverà il nome che l'utente ha inserito nell'elemento di input e lo invierà tramite il metodo POST al server. Dopo aver ricevuto una risposta dal server, sostituisci con esso il contenuto dell'elemento div nella pagina.

Un esempio di funzionamento AJAX

Un esempio di funzionamento AJAX



Principali articoli correlati