AJAX es una herramienta clave en el desarrollo moderno de aplicaciones web. Le permite enviar y recibir datos de forma asincrónica al servidor y luego analizarlos en JavaScript. Ajax es la abreviatura de JavaScript asíncrono y XML (JavaScript asíncrono y XML).
El nombre de la especificación del núcleo de AJAX se hereda del objeto JavaScript utilizado para crear e iniciar solicitudes: XMLHTTPREQUEST. Hay dos niveles de esta especificación. Todos los navegadores convencionales implementan el primer nivel, que representa el nivel básico de funcionalidad. El segundo nivel extiende la especificación inicial, incorpora eventos adicionales y algunas características para facilitar la colaboración con elementos de formulario, y admite algunas especificaciones relacionadas.
1. Ajax comienza
La clave para AJAX se encuentra en el objeto xmlhttprequest, y la forma de comprender este objeto es mirar un ejemplo. El siguiente código muestra el uso simple del objeto xmlhttprequest:
<! Doctype html> <html lang = "en"> <fead> <meta charset = "utf-8"> <title> ejemplo </title> </head> <body> <div> <botton> manzanas </boton> <botte> cerezas </boton> <botte> bootine </boton> </div> <Div Id = "Atil Botones var = document.getElementsBytagName ("botón"); for (var i = 0; i <button.length; i ++) {botones [i] .Onclick = maneButtonPress; } // El script llamará a esta función para responder a la función de evento de clic del control del botón HANGUTTONPRESS (E) {// Cree un nuevo objeto xmlhttprequest var httprequest = new xmlhttprequest (); // Establecer un controlador de eventos para el evento OnreadyStateChange httprequest.onreadyStateChange = HandlerEponse; // Use el método abierto para especificar el método HTTP y la URL para solicitar (es decir, indique el objeto httprequest lo que desea hacer) httprequest.open ("get", e.target.innerhtml+". Html"); // No se envían datos al servidor aquí, por lo que el método de envío no tiene parámetros disponibles httprequest.send (); } // procesar la respuesta // Una vez que el script llame al método de envío, el navegador enviará una solicitud al servidor en segundo plano. Debido a que la solicitud se procesa en segundo plano, Ajax se basa en eventos para informar el progreso de la solicitud. HandlerAponse de la función (e) {// Cuando se activa el evento OnreadyStateChange, el navegador pasará un objeto de evento a la función de controlador especificada, y la propiedad de destino se establecerá en el xmlhttprequest asociado con este evento si (e.target.readyState == xmlhttprequest.done && e.target.stataus == 200) {// document.getElementById ("Target"). InnerHtml = e.target.ResponSetext; // Mostrar el contenido del documento solicitado}} </script> </body> </html>Tres documentación adicional es muy simple:
<! DocType html> <html lang = "en"> <head> <meta charset = "utf-8"> <title> manzanas </title> <style> img {float: izquierda; relleno: 2px; margen: 5px; borde: doble negro; color de fondo: lightgrey; Ancho: 100px; Height: 100px;} </style> </head> <body> <p> <img src = "../ img/show-page/img_apple.jpg"/> página para manzanas. </p> </body> </html>El efecto se muestra en la figura a continuación:
A medida que el usuario hace clic en cada botón de fruta, el navegador se ejecuta asíncronamente y recupera el documento solicitado, mientras que el documento principal no se vuelve a cargar. Este es un comportamiento típico de Ajax.
2. Uso de eventos AJAX
Después de crear y explorar un ejemplo simple, puede comenzar a profundizar en las características admitidas por el objeto XMLHTTPRequest y cómo usarlas en su solicitud. El punto de partida son los eventos adicionales definidos en la especificación de segundo nivel:
La mayoría de estos eventos se activan en un momento específico durante la solicitud. Los dos eventos son excepciones, ReadyStateChange y Progress, que se pueden activar varias veces para proporcionar actualizaciones de progreso.
Cuando estos eventos están programados, el navegador utiliza un objeto de evento regular para el evento ReadyStateChange y un objeto ProgressEvent para otros eventos. El objeto ProgressEvent define a todos los miembros del objeto del evento y agrega estos miembros descritos en la siguiente figura:
El siguiente código muestra cómo usar estos eventos:
<! DocType html> <html lang = "en"> <head> <meta charset = "utf-8"> <title> Ejemplo </title> <style> table {margin: 10px; border-colapse: colapso; float: izquierda;} div {margin: 10px;} td, th {relleno: 4px;} </ystye> </head> <body> <div> <boton> manzanas </botón> <botón> cerezas </botón> <botón> buttonas </boton> </div> <table id = "eventos"> </table> <divdi = "objetivo" type = "Application/JavaScript"> Var Botones = document.getElementsBytagName ("botón"); for (var i = 0; i <button.length; i ++) {botones [i] .Onclick = maneButtonPress; } var httprequest; function hangleButtonPress (e) {clearEventDetails (); httprequest = new xmlhttprequest (); httprequest.OnreadyStateChange = HandlerEponse; httprequest.onerror = handleError; httprequest.onload = handleload ;; httprequest.onloadend = handleloadend; httprequest.OnloadStart = handleloadStart ;; httprequest.onProgress = handleProgress; httprequest.open ("get", e.target.innerhtml+". html"); httprequest.send (); } function handlerEponse (e) {displayEventDetails ("ReadyState ("+httprequest.readyState+")") if (e.target.readyState == xmlhttprequest.done && e.target.status == 200) {document.getEmementByid ("Target"). Innerhtmll = E.TargetTettet. }} function handleError (e) {displayEventDetails ("error", e);} handLELOAd (e) {displayEventDetails ("load", e);} function handLElaadend (e) {displayEventDetails ("loadend", e);} function handLeloadend (e) {displayEventDetails (e); función handleloadstart (e) {displayEventDetails ("LoadStart", e);} function handleProgress (e) {displayEventDetails ("progreso", e);} function clearEventDetails () {document.getElementById ("eventos"). innerhtml = "<tr> <th> event </th> <th> longitudComputable </th> <th> cargado </th> <th> total </th>"; } función DISPOSTEVENTDETAILS (EventName, E) {if (e) {document.getElementById ("eventos"). innerhtml+= "<tr> <td>"+eventName+"</td> <td>"+e.lengthomutable+"</td> <td>"+e.loaded+"</td> <td>"+"+"+"+"+"+"+"+" e.total+"</td> </tr>"; } else {document.getElementById ("eventos"). innerhtml+= "<tr> <td>"+eventname+"</td> <td> na </td> <td> na </td> <td> na </td> <td> na </td> </tr>"; }} </script> </body> </html>Esta es una variación del ejemplo anterior, registra un controlador para algunos eventos y crea un registro para cada evento procesado en un elemento de tabla. A partir de la siguiente imagen, puede ver cómo el navegador Firefox desencadena estos eventos.
3. Manejar errores
Se deben prestar atención a dos tipos de errores al usar AJAX. La diferencia entre ellos proviene de diferentes perspectivas.
El primer tipo de error es un problema visto desde la perspectiva del objeto xmlhttprequest: algunos factores evitan que la solicitud se envíe al servidor. Por ejemplo, el DNS no puede resolver el nombre de host, la solicitud de conexión se niega o la URL no es válida.
El segundo tipo de problema es el problema visto desde la perspectiva de la aplicación, no el objeto xmlhttprequest. Se producen cuando la solicitud se envía con éxito al servidor, que recibe la solicitud, procesa y genera una respuesta, pero la respuesta no apunta a lo que espera. Por ejemplo, si la URL solicitada no existe, este tipo de problema ocurre.
Hay tres formas de lidiar con estos errores, como se muestra en el siguiente código:
3.1 Errores de ajuste de manejo
El primer tipo de problema que debe tratarse es pasar datos incorrectos al objeto XMLHTTPresquest, como una URL incorrecta. Son extremadamente propensos a ocurrir al generar URL en función de la entrada del usuario. Para simular este tipo de problema, el documento anterior tiene un botón que agrega una URL mala de la etiqueta (URL incorrecta). Al presionar este botón, llamará al método abierto en el siguiente formulario:
httprequest.open ("get", "http: //")
Este es un error que evita que la solicitud se ejecute, y se lanza un error cuando se produce un evento como este en el objeto xmlhttprequest. Esto significa que una declaración de intento ... se necesita para rodear el código que establece la solicitud, así:
Pruebe {... httprequest.open ("get", "http: //") ... httprequest.send (); } capt (error) {displayRormsg ("Try/Catch", Error.message)}La cláusula de captura le da la oportunidad de recuperarse del error. Puede elegir solicitar al usuario un valor, o volver a la URL predeterminada, o simplemente descartar la solicitud. En este ejemplo, se llama a la función DisplayRormsg para mostrar el mensaje de error.
3.2 Errores de solicitud de procesamiento
El segundo tipo de error ocurre cuando se ha generado la solicitud, pero hay otros errores. Para simular este tipo de problema, se agregó un botón etiquetado como host (host de error) en el ejemplo. Cuando se presiona este botón, se llamará al método abierto para acceder a una URL no disponible:
httprequest.open ("get", http: //www.ycdoitt.com/nopage.html)Hay dos problemas con esta URL. El primer problema es que el nombre de host no puede ser resuelto por DNS, por lo que el navegador no puede generar una conexión de servidor. Este problema sabe que el objeto xmlhttprequest solo se vuelve obvio cuando comienza a generar la solicitud, por lo que señala errores de dos maneras. Si registra un oyente para un evento de error, el navegador enviará un objeto de evento a su oyente. Aquí están las funciones utilizadas en el ejemplo:
función handleError (e) {displayErmormsg ("Evento de error", httprequest.status + httprequest.statusText); }Cuando ocurren dichos errores, el grado de información que se puede obtener del objeto XMLHTTPREQUEST depende del navegador. Desafortunadamente, en la mayoría de los casos, se obtendrá el estado con un valor de 0 y un valor en blanco Statustext.
El segundo problema es que la URL y la solicitud generada tienen diferentes fuentes, que no están permitidas de forma predeterminada. Por lo general, solo puede enviar solicitudes AJAX a la URL del mismo origen que carga el script. Cuando un navegador informa este problema, se puede lanzar un error o se puede activar un evento de error. Diferentes navegadores lo manejan de manera diferente. Diferentes navegadores también verifican la fuente en diferentes puntos en el tiempo, lo que significa que el navegador no siempre se puede ver destacando el mismo problema. El intercambio de recursos de origen cruzado se puede utilizar para evitar restricciones homólogas.
3.3 Manejo de errores de aplicación
El último tipo de error ocurre cuando la solicitud se completa con éxito (desde la perspectiva del objeto xmlhttprequest), pero no devuelve los datos que desea. Para crear tales problemas, agregue un botón con la etiqueta de pepino en el ejemplo anterior. Al presionar este botón, generará una URL de solicitud similar a los botones de manzanas, cerezas y plátanos, pero el documento Cucumber.html no existe en el servidor.
No hay error en este proceso en sí (porque la solicitud se ha completado), y es necesario determinar qué está sucediendo en función del atributo de estado. Al solicitar un documento existente, se obtendrá el código de estado 404, lo que significa que el servidor no puede encontrar el documento solicitado. Puede ver cómo el ejemplo maneja códigos de estado distintos a 200 (es decir, bien):
if (httprequest.status == 200) {target.innerhtml = httprequest.esponsetext; } else {document.getElementById ("statusmsg"). innerhtml = "status:" + httprequest.status + "" + httprequest.statusText; }En este ejemplo, los valores de estado y estatustext simplemente se muestran. En aplicaciones reales, la recuperación debe llevarse a cabo de una manera útil y significativa (como mostrar contenido alternativo o advertir a los usuarios que existe un problema, dependiendo de cuál sea más adecuado para la aplicación).
4. Obtén y confirme los encabezados
Usando el objeto xmlhttprequest, puede establecer el encabezado de solicitud enviado al servidor y el encabezado en la respuesta del servidor.
4.1 Sobrescribir el método HTTP para las solicitudes
Por lo general, no es necesario agregar o modificar el encabezado en la solicitud AJAX. El navegador sabe qué enviar, y el servidor sabe cómo responder. Sin embargo, hay varias excepciones. El primero es el encabezado del método X-HTTP.
El estándar HTTP a menudo se usa para solicitar y transmitir documentos HTML en Internet, y define muchos métodos. La mayoría de la gente sabe sobre Get and Post porque son los más utilizados. Sin embargo, existen otros métodos (incluidos Put y Elimine) que se utilizan para dar significado a la URL solicitada al servidor, y este uso está en aumento. Por ejemplo, si desea ver un registro de usuario, puede generar dicha solicitud:
httprequest.open ("get", "http: // myserver/registros/freeman/adam");Aquí solo se muestran el método HTTP y la URL solicitada. Para que esta solicitud funcione sin problemas, el lado del servidor debe poder comprender la solicitud de la aplicación y convertirla en un dato adecuado que se enviará al servidor. Si desea eliminar los datos, puede escribirlos así:
httprequest.open (" Eliminar ", "http: // myserver/registros/freeman/adam");La clave aquí es expresar lo que desea que haga el servidor a través de HTTP, en lugar de codificarlo en la URL de alguna manera.
El problema con el uso de métodos HTTP de esta manera es que muchas tecnologías web convencionales solo admiten Get Get and Post, y muchos firewalls solo permiten que sean las solicitudes de Get y Post. Existe un enfoque idiomático para evitar esta limitación, que es utilizar el encabezado X-HTTP-Method-Override para especificar el método HTTP que desea utilizar, pero el formulario se comercializa y envía una solicitud posterior. La demostración del código es la siguiente:
<! Doctype html> <html lang = "en"> <fead> <meta charset = "utf-8"> <title> ejemplo </title> </head> <body> <div> <botte> manzanas </boton> <botton> cerezas </botón> <botón> buttonas </boton> </div> <Div Id = "objetivo" document.getElementsByTagName ("Botón"); for (var i = 0; i <button.length; i ++) {botones [i] .Onclick = maneButtonPress; } var httprequest; function hangleButtonPress (e) {httprequest = new xmlhttprequest (); httprequest.OnreadyStateChange = HandlerEponse; httprequest.open ("get", e.target.innerhtml+". html"); httprequest.setRequestHeader ("x-http-method-override", "eliminar"); httprequest.send (); } function handleError (e) {displayErmormsg ("Evento de error", httprequest.status+httprequest.statusText); } function handlereSponse () {if (httprequest.readyState == 4 && httprequest.status == 200) {document.getElementById ("target"). innerhtml = httprequest.responsetext; }} </script> </body> </html>En este ejemplo, el método SetRequestHeader en el objeto XMLHTTPRequest se usa para indicar que la solicitud se desea procesar en forma de un método HTTP Eliminar. Tenga en cuenta que configuré este encabezado solo después de llamar al método abierto. Si intenta usar el método SetRequestHeader antes del método abierto, el objeto XMLHTTPRequest arroja un error.
PS: La sobrescribencia de HTTP requiere que el marco de aplicaciones web del lado del servidor comprenda la convención de X-HTTP-Method-Override, y su aplicación del lado del servidor debe configurarse para encontrar y comprender esos métodos menos HTTP.
4.2 Desactivar el almacenamiento en caché de contenido
El segundo encabezado útil que se puede agregar a las solicitudes de AJAX es el control de caché, que es especialmente útil al escribir y depurar scripts. Algunos navegadores de caché contenido obtenido a través de solicitudes AJAX y no lo solicitarán nuevamente durante la sesión de navegación. Para el ejemplo anterior, significa que los cambios en Apples.html, Cherries.html y Bananas.html no se reflejarán inmediatamente en el navegador. El siguiente código muestra cómo establecer encabezados para evitar esto:
httprequest = new xmlhttprequest (); httprequest.OnreadyStateChange = HandlerEponse; httprequest.open ("get", e.target.innerhtml+". html"); httprequest.setRequestHeader ("Cache-Control", "No-Cache"); httprequest.send ();La forma de establecer el encabezado es la misma que en el ejemplo anterior, pero esta vez el encabezado es con control de caché, y el valor deseado es sin caché. Después de colocar esta declaración, si el contenido solicitado a través de los cambios de AJAX, se reflejará la próxima vez que se solicite el documento.
4.3 Lea el encabezado de respuesta
El encabezado HTTP enviado por el servidor cuando responde a una solicitud AJAX se puede leer a través de los métodos GetResponseHeader y GetAllResponseHeaders. En la mayoría de los casos, no necesita preocuparse por lo que hay en el encabezado, porque son parte de las transacciones interactivas entre el navegador y el servidor. El siguiente código muestra cómo usar esta propiedad:
<! Doctype html> <html lang = "en"> <head> <meta charset = "utf-8"> <meta content = "width = dispositivo-width, user-scalable = no" name = "viewport" /> <meta name = "autor" Content = "Ye chaoluka" /> <meta name = "Descripción" Content = "un ejemplo de ejemplo" /Título " /Título" href = "../ img/ycdoit.ico" type = "image/x-icon" rel = "shortcut icon"/> <style> #theHheaders, #coeader {border: mediano sólido negro; relleno: 2px; margin: 2px;} </ystye> </thead> <body> <div> <boton> apples </boton> <boton> buttone </button> button </button </button </button </button </button </button </button </button </button </button </button </button </button </button </Button </Button </Button </Button </Button </Button </button </Button </Button </Button </Button </Button> Button <botton> bananas </boton> </div> <div id = "Cheader"> </div> <div id = "Altheaders"> </div> <div id = "Target"> Presione un botón </div> <script> Var Buttons = document.getElementsByTagName ("Button"); for (var i = 0; i <button.length; i ++) {botones [i] .Onclick = maneButtonPress; } var httprequest; function hangleButtonPress (e) {httprequest = new xmlhttprequest (); httprequest.OnreadyStateChange = HandlerEponse; httprequest.open ("get", e.target.innerhtml+". html"); httprequest.setRequestHeader ("Cache-Control", "No-Cache"); httprequest.send (); } function handlereSponse () {if (httprequest.readyState == 2) {document.getElementById ("theRheaders"). innerhtml = httprequest.getallResponseHeaders (); document.getElementById ("coeador"). innerhtml = httprequest.getResponseHeader ("Content-type"); } else if (httprequest.readyState == 4 && httprequest.status == 200) {document.getElementById ("target"). innerhtml = httprequest.esponsetext; }} </script> </body> </html>Las representaciones son las siguientes:
Según esta cifra, podemos ver que el software del servidor web que el servidor de desarrollo está ejecutando es la idea IntelliJ 15.0.4, y la última vez que se modificó el documento Apples.html fue el 27 de junio (pero la captura de pantalla fue el 5 de julio).