Movatterモバイル変換


[0]ホーム

URL:


MDN Web Docs

Esta página ha sido traducida del inglés por la comunidad. Aprende más y únete a la comunidad de MDN Web Docs.

Utilizando XMLHttpRequest

BaselineWidely available *

En esta guía le echaremos un vistazo a cómo usarXMLHttpRequest para enviar solicitudesHTTPcon el objetivo de intercambiar datos entre el sitio web y el servidor.

Se incluyen ejemplos, tanto para los casos de uso comunes deXMLHttpRequest,como para los más inusuales.

Para enviar una solicitud HTTP, cree un objetoXMLHttpRequest, abra una URL yenvíe la solicitud. Una vez que la transacción haya sido completada, el objetocontendrá información útil tal como el cuerpo de la respuesta y el estadoHTTPstatus del resultado.

js
function reqListener() {  console.log(this.responseText);}var oReq = new XMLHttpRequest();oReq.addEventListener("load", reqListener);oReq.open("GET", "http://www.example.org/example.txt");oReq.send();

Tipos de peticiones

Una petición realizada a través deXMLHttpRequest puede obtener los datos de una estas dos maneras,de forma asíncrona o sincrónica. El tipo de petición viene dictado por el argumento opcionalasync(el tercer argumento) que se establece en el métodoXMLHttpRequest.open(). Si este argumento estrue ono se especifica, laXMLHttpRequest se procesa de forma asíncrona, de lo contrarioel proceso se realiza de forma síncrona. Una discusión detallada y demostraciones de estosde estos dos tipos de peticiones en la páginapeticiones síncronasy asíncronas. No utilice solicitudes sincrónicas fuera de los WebWorkers.

Nota:A partir de Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), las peticiones síncronas en el hilo principal han sido marcadas como obsoletas debido a los efectos negativos en la experiencia del usuario.

Nota:La función constructoraXMLHttpRequest no se limita a los documentos XML. Comienza con"XML" porque cuando se creó el formato principal que se utilizaba originalmente para el intercambio de datos asíncrono era XML.

Manejando las respuestas

Hay varios tipos deatributos derespuesta definidos por la especificación del estándar para elconstructorXMLHttpRequest(). Esto le diceal cliente que realiza elXMLHttpRequest información importante sobre el estadode la respuesta. Algunos casos en los que tratar con tipos de respuesta no textuales puede implicar algunamanipulación y análisis como se describen en las siguientes secciones.

Analizar y manipular la propiedad responseXML

Si utilizaXMLHttpRequest para obtener el contenido de un documento XML remoto, la propiedadresponseXML será un objeto DOMque contiene un documento XML analizado. Esto podría resultar difícil de manipular y analizar.Principalmente hay cuatro formas de analizar este documento XML:

  1. UsandoXPath para dirigir (o apuntar a) partesdel mismo.
  2. ManualmenteAnalizar yserializar el XML a cadenas u objetos.
  3. UsandoXMLSerializer para serializarárboles DOM a cadenas o aarchivos.
  4. RegExp se puede utilizar si siempre se conoce el contenido del documento XMLde antemano. Es posible que desee eliminar los saltos de línea, si utilizaRegExp paraescanear en lo que respecta a los saltos de línea. Sin embargo, este método es un "último recurso" ya que si elcódigo XML cambia ligeramente, el método probablemente fallará.

Nota:XMLHttpRequest ahora puede interpretar HTML por tiutilizando la propiedadresponseXML. Lea elartículo sobreHTMLen XMLHttpRequest para aprender como hacerlo.

Procesamiento de una propiedad responseText que contiene un documento HTML

Si usasXMLHttpRequest para obtener el contenido de una página web HTML remota, la propiedadresponseText es una cadenaque contiene el HTML en bruto. Esto podría resultar difícil de manipular y analizar. Principalmente hay trestres formas de analizar y parsear esta cadena de HTML en bruto:

  1. Utilizar la propiedadXMLHttpRequest.responseXML como se explica en el artículoHTML enXMLHttpRequest.
  2. Inyectar el contenido en el cuerpo de unfragmento de documento mediantefragment.body.innerHTML y recorrer el DOM del fragmento.
  3. RegExp puede utilizarse si siempre se conoce el contenido del HTMLresponseText de antemano. Es posible que desee eliminar los saltos de línea, si utilizaRegExp paraescanear en lo que respecta a los saltos de línea. Sin embargo, este método es un "último recurso"ya que si el código HTML cambia ligeramente, el método probablemente fallará.

Manejo de datos binarios

AunqueXMLHttpRequest se utiliza normalmente para enviar y recibirdatos textuales, puede utilizarse para enviar y recibir contenido binario. Existen variosmétodos probados para forzar a la respuesta de unXMLHttpRequest para que envíe datosbinarios. Se trata de utilizar la funciónoverrideMimeType() en el objetoXMLHttpRequest y es unasolución viable.

js
var oReq = new XMLHttpRequest();oReq.open("GET", url);// recuperar los datos sin procesar como una cadena binariaoReq.overrideMimeType("text/plain; charset=x-user-defined");/* ... */

Sin embargo, existen técnicas más modernas, ya que elresponseType admite ahora unaserie de tipos de contenido adicionales, lo que facilita el envío y la recepción de datos binarios.

Por ejemplo, considere este fragmento, que utiliza elresponseType de"arraybuffer" para obtener el contenido remoto en un objetoArrayBufferque almacena los datos binarios en bruto.

js
var oReq = new XMLHttpRequest();oReq.onload = function (e) {  var arraybuffer = oReq.response; // no responseText  /* ... */};oReq.open("GET", url);oReq.responseType = "arraybuffer";oReq.send();

Para ver más ejemplos, consulte la páginaEnvío yrecepción de datos binarios

Seguimiento del progreso

XMLHttpRequest proporciona la capacidad de escuchar varios eventos que puedenocurrir mientras se procesa la solicitud. Esto incluye notificaciones periódicasdel progreso, notificaciones de error, etc.

La implementación para la monitorización de eventos DOMprogress de transferenciasXMLHttpRequestsigue laespecificación de eventos de progreso: estoseventos implementan la interfazProgressEvent. Los eventos reales que puedes monitorizarpara determinar el estado de una transferencia en curso son:

progress

La cantidad de datos que se han recibido ha cambiado.

load

La transferencia se ha completado; todos los datos están ahora en elresponse.

js
var oReq = new XMLHttpRequest();oReq.addEventListener("progress", updateProgress);oReq.addEventListener("load", transferComplete);oReq.addEventListener("error", transferFailed);oReq.addEventListener("abort", transferCanceled);oReq.open();// ...// progreso de las transferencias del servidor al cliente (descargas)function updateProgress(oEvent) {  if (oEvent.lengthComputable) {    var percentComplete = (oEvent.loaded / oEvent.total) * 100;    // ...  } else {    // No se puede calcular la información de progreso ya que el tamaño total es desconocido  }}function transferComplete(evt) {  console.log("La transferencia se ha completado.");}function transferFailed(evt) {  console.log("Se ha producido un error al transferir el archivo.");}function transferCanceled(evt) {  console.log("La transferencia ha sido cancelada por el usuario.");}

Las líneas 3-6 añaden escuchadores de eventos para los distintos eventos que se envían al realizar unatransferencia de datos utilizandoXMLHttpRequest.

Nota:Tienes que añadir los escuchadores de eventos antes de llamar aopen() en la petición. De lo contrario, los eventos `progress no se dispararán.

El manejador de eventos de progreso, especificado por la funciónupdateProgress() eneste ejemplo, recibe el número total de bytes a transferir así como el número debytes transferidos hasta el momento en los campostotal yloaded del evento.Sin embargo, si el campolengthComputable es falso, la longitud totalno se conoce y será cero.

Los eventos de progreso existen tanto para las transferencias de descarga como de subida. Los eventos de descargase disparan en el propio objetoXMLHttpRequest, como se muestra en el ejemplo anterior.Los eventos de subida se disparan en el objetoXMLHttpRequest.upload, como se muestraa continuación:

js
var oReq = new XMLHttpRequest();oReq.upload.addEventListener("progress", updateProgress);oReq.upload.addEventListener("load", transferComplete);oReq.upload.addEventListener("error", transferFailed);oReq.upload.addEventListener("abort", transferCanceled);oReq.open();

Nota:Los eventos de progreso no están disponibles para el protocolofile:.

Nota:A partir de Gecko 9.0, se puede confiar en que los eventos de progreso lleguen para cada trozo de datos recibidos, incluyendo el último trozo en los casos en los que se recibe el último paquete y se cierra la conexión antes de que se dispare el evento de progreso. En este caso, el evento de progreso se dispara automáticamente cuando se produce el evento de carga para ese paquete. Esto te permite ahora monitorizar de forma fiable el progreso observando únicamente el evento "progress".

Nota:A partir de Gecko 12.0, si su evento de progreso es llamado con unresponseType de "moz-blob", el valor de la respuesta es unBlob que contiene los datos recibidos hasta el momento.

También se pueden detectar las tres condiciones de finalización de la carga (abort,load, oerror) utilizando el eventoloadend:

js
req.addEventListener("loadend", loadEnd);function loadEnd(e) {  console.log(    "La transferencia ha terminado (aunque no sabemos si ha tenido éxito o no).",  );}

Ten en cuenta que no hay forma de estar seguros, a partir de la información recibida por el eventode la información recibida por el eventoloadend, en cuanto a la condición que causó la terminación de la operación;sin embargo, puede utilizar esto para manejar las tareas que deben realizarse en todos losescenarios de fin de transferencia.

Envío de formularios y subida de archivos

Las instancias deXMLHttpRequest pueden utilizarse para enviar formularios de dos maneras:

  • usando sólo AJAX
  • utilizando la APIFormData

El uso de la APIFormData es el más sencillo y rápido, pero tiene ladesventaja de que los datos recogidos no pueden serstringificados.

Utilizar sólo AJAX es más complejo, pero suele ser más flexible y potente.

Usando nada más queXMLHttpRequest

El envío de formularios sin la APIFormData no necesita de otras APIs parala mayoría de los casos de uso. El único caso en el que necesita una API adicional essi quieresubir uno o más archivos, donde se utiliza la APIFileReader.

Una breve introducción a los métodos de envío

Un html<form> puede ser enviado de cuatro maneras:

  • utilizando el métodoPOST y estableciendo el atributoenctype aapplication/x-www-form-urlencoded (por defecto);
  • utilizando el métodoPOST y estableciendo el atributoenctype comotext/plain;
  • utilizando el métodoPOST y estableciendo el atributoenctype comomultipart/form-data;
  • utilizando el métodoGET (en este caso el atributoenctype seserá ignorado).

Consideremos ahora el envío de un formulario que contiene sólo dos campos, llamadosfoo ybaz. Si está utilizando el métodoPOST elservidor recibirá una cadena similar a uno de los tres ejemplos siguientes, dependiendodependiendo del tipo de codificación que esté utilizando:

  • Método:POST; Tipo de codificación:application/x-www-form-urlencoded (por defecto):

    Content-Type: application/x-www-form-urlencodedfoo=bar&baz=The+first+line.%0D%0AThe+second+line.%0D%0A
  • Método:POST; Tipo de codificación:text/plain:

    Content-Type: text/plainfoo=barbaz=The first line.The second line.
  • Método:POST; Tipo de codificación:multipart/form-data:

    Content-Type: multipart/form-data; boundary=---------------------------314911788813839-----------------------------314911788813839Content-Disposition: form-data; name="foo"bar-----------------------------314911788813839Content-Disposition: form-data; name="baz"The first line.The second line.-----------------------------314911788813839--

Sin embargo, si utiliza el métodoGET, se añadirá a la URL una cadena como la siguiente:

?foo=bar&baz=The%20first%20line.%0AThe%20second%20line.

Un pequeño framework vanilla

Todos estos efectos son realizados automáticamente por el navegador web cada vez que se envía un<form>. Si quieres realizar los mismos efectos usando JavaScript tiene quetiene que instruir al intérprete sobretodo. Por lo tanto, la forma de enviar formulariosenpuro AJAX es demasiado complejo para ser explicado aquí en detalle. Por esta razón,aquí colocamosun completo (aunque didáctico) framework, capaz de utilizar las cuatroformas deenviar, y desubir archivos:

html
<!doctype html><html>  <head>    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />    <title>Envío de formularios con AJAX puro &ndash; MDN</title>    <script type="text/javascript">      "use strict";      /*\      |*|      |*|  :: XMLHttpRequest.prototype.sendAsBinary() Polyfill ::      |*|      |*|  https://developer.mozilla.org/es/docs/DOM/XMLHttpRequest#sendAsBinary()      \*/      if (!XMLHttpRequest.prototype.sendAsBinary) {        XMLHttpRequest.prototype.sendAsBinary = function (sData) {          var nBytes = sData.length,            ui8Data = new Uint8Array(nBytes);          for (var nIdx = 0; nIdx < nBytes; nIdx++) {            ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff;          }          /* enviar como ArrayBufferView...: */          this.send(ui8Data);          /* ...o como ArrayBuffer (legacy)...: this.send(ui8Data.buffer); */        };      }      /*\      |*|      |*|  :: AJAX Framework de envío de formulario ::      |*|      |*|  https://developer.mozilla.org/es/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest      |*|      |*|  Este framework está publicado bajo la licencia pública GNU, versión 3 o posterior.      |*|  https://www.gnu.org/licenses/gpl-3.0-standalone.html      |*|      |*|  Sintaxis:      |*|      |*|   AJAXSubmit(HTMLFormElement);      \*/      var AJAXSubmit = (function () {        function ajaxSuccess() {          /* console.log("AJAXSubmit - ¡Éxito!"); */          console.log(this.responseText);          /* puedes obtener los datos serializados a través de la propiedad personalizada "submittedData": */          /* console.log(JSON.stringify(this.submittedData)); */        }        function submitData(oData) {          /* la petición AJAX... */          var oAjaxReq = new XMLHttpRequest();          oAjaxReq.submittedData = oData;          oAjaxReq.onload = ajaxSuccess;          if (oData.technique === 0) {            /* el método es GET */            oAjaxReq.open(              "get",              oData.receiver.replace(                /(?:\?.*)?$/,                oData.segments.length > 0 ? "?" + oData.segments.join("&") : "",              ),              true,            );            oAjaxReq.send(null);          } else {            /* el método es POST */            oAjaxReq.open("post", oData.receiver, true);            if (oData.technique === 3) {              /* enctype es multipart/form-data */              var sBoundary =                "---------------------------" + Date.now().toString(16);              oAjaxReq.setRequestHeader(                "Content-Type",                "multipart\/form-data; boundary=" + sBoundary,              );              oAjaxReq.sendAsBinary(                "--" +                  sBoundary +                  "\r\n" +                  oData.segments.join("--" + sBoundary + "\r\n") +                  "--" +                  sBoundary +                  "--\r\n",              );            } else {              /* enctype es application/x-www-form-urlencoded or text/plain */              oAjaxReq.setRequestHeader("Content-Type", oData.contentType);              oAjaxReq.send(                oData.segments.join(oData.technique === 2 ? "\r\n" : "&"),              );            }          }        }        function processStatus(oData) {          if (oData.status > 0) {            return;          }          /* ¡el formulario está ahora totalmente serializado! haz algo antes de enviarlo al servidor... */          /* doSomething(oData); */          /* console.log("AJAXSubmit - El formulario está ahora serializado. Enviando..."); */          submitData(oData);        }        function pushSegment(oFREvt) {          this.owner.segments[this.segmentIdx] += oFREvt.target.result + "\r\n";          this.owner.status--;          processStatus(this.owner);        }        function plainEscape(sText) {          /* ¿Cómo debo tratar la codificación de un formulario text/plain?       ¿Qué caracteres no están permitidos? Esto es lo que supongo..: */          /* "4\3\7 - Einstein dijo E=mc2" ----> "4\\3\\7\ -\ Einstein\ dijo\ E\=mc2" */          return sText.replace(/[\s\=\\]/g, "\\$&");        }        function SubmitRequest(oTarget) {          var nFile,            sFieldType,            oField,            oSegmReq,            oFile,            bIsPost = oTarget.method.toLowerCase() === "post";          /* console.log("AJAXSubmit - Serializando formulario..."); */          this.contentType =            bIsPost && oTarget.enctype              ? oTarget.enctype              : "application\/x-www-form-urlencoded";          this.technique = bIsPost            ? this.contentType === "multipart\/form-data"              ? 3              : this.contentType === "text\/plain"                ? 2                : 1            : 0;          this.receiver = oTarget.action;          this.status = 0;          this.segments = [];          var fFilter = this.technique === 2 ? plainEscape : escape;          for (var nItem = 0; nItem < oTarget.elements.length; nItem++) {            oField = oTarget.elements[nItem];            if (!oField.hasAttribute("name")) {              continue;            }            sFieldType =              oField.nodeName.toUpperCase() === "INPUT" &&              oField.hasAttribute("type")                ? oField.getAttribute("type").toUpperCase()                : "TEXT";            if (sFieldType === "FILE" && oField.files.length > 0) {              if (this.technique === 3) {                /* enctype es multipart/form-data */                for (nFile = 0; nFile < oField.files.length; nFile++) {                  oFile = oField.files[nFile];                  oSegmReq = new FileReader();                  /* (propiedades personalizadas:) */                  oSegmReq.segmentIdx = this.segments.length;                  oSegmReq.owner = this;                  /* (fin de las propiedades personalizadas) */                  oSegmReq.onload = pushSegment;                  this.segments.push(                    'Content-Disposition: form-data; name="' +                      oField.name +                      '"; filename="' +                      oFile.name +                      '"\r\nContent-Type: ' +                      oFile.type +                      "\r\n\r\n",                  );                  this.status++;                  oSegmReq.readAsBinaryString(oFile);                }              } else {                /* enctype es application/x-www-form-urlencoded or text/plain or             el método es GET: ¡los archivos no se enviarán! */                for (                  nFile = 0;                  nFile < oField.files.length;                  this.segments.push(                    fFilter(oField.name) +                      "=" +                      fFilter(oField.files[nFile++].name),                  )                );              }            } else if (              (sFieldType !== "RADIO" && sFieldType !== "CHECKBOX") ||              oField.checked            ) {              /* NOTA: esto enviará _todos_ los botones de envío. Detectar el correcto no es trivial. */              /* el tipo de campo no es FILE o es FILE pero está vacío */              this.segments.push(                this.technique === 3 /* enctype es multipart/form-data */                  ? 'Content-Disposition: form-data; name="' +                      oField.name +                      '"\r\n\r\n' +                      oField.value +                      "\r\n"                  : /* enctype es application/x-www-form-urlencoded o text/plain el método es GET */                    fFilter(oField.name) + "=" + fFilter(oField.value),              );            }          }          processStatus(this);        }        return function (oFormElement) {          if (!oFormElement.action) {            return;          }          new SubmitRequest(oFormElement);        };      })();    </script>  </head>  <body>    <h1>Envío de formularios con AJAX puro</h1>    <h2>Utilizando el método GET</h2>    <form      action="register.php"      method="get"      onsubmit="AJAXSubmit(this); return false;">      <fieldset>        <legend>Ejemplo de registro</legend>        <p>          Nombre: <input type="text" name="firstname" /><br />          Apellido: <input type="text" name="lastname" />        </p>        <p>          <input type="submit" value="Submit" />        </p>      </fieldset>    </form>    <h2>Utilizando el método POST</h2>    <h3>Enctype: application/x-www-form-urlencoded (por defecto)</h3>    <form      action="register.php"      method="post"      onsubmit="AJAXSubmit(this); return false;">      <fieldset>        <legend>Ejemplo de registro</legend>        <p>          Nombre: <input type="text" name="firstname" /><br />          Apellido: <input type="text" name="lastname" />        </p>        <p>          <input type="submit" value="Submit" />        </p>      </fieldset>    </form>    <h3>Enctype: text/plain</h3>    <form      action="register.php"      method="post"      enctype="text/plain"      onsubmit="AJAXSubmit(this); return false;">      <fieldset>        <legend>Ejemplo de registro</legend>        <p>Tu nombre: <input type="text" name="user" /></p>        <p>          Tu mensaje:<br />          <textarea name="message" cols="40" rows="8"></textarea>        </p>        <p>          <input type="submit" value="Submit" />        </p>      </fieldset>    </form>    <h3>Enctype: multipart/form-data</h3>    <form      action="register.php"      method="post"      enctype="multipart/form-data"      onsubmit="AJAXSubmit(this); return false;">      <fieldset>        <legend>Ejemplo de subida</legend>        <p>          Nombre: <input type="text" name="firstname" /><br />          Apellido: <input type="text" name="lastname" /><br />          Sexo:          <input type="radio" name="sex" value="male" />          <label for="sex_male">Hombre</label>          <input type="radio" name="sex" value="female" />          <label for="sex_female">Mujer</label><br />          Contraseña: <input type="password" name="secret" /><br />          ¿Qué prefieres?:          <select name="image_type">            <option>Libros</option>            <option>Cine</option>            <option>TV</option>          </select>        </p>        <p>          Envía tus fotos:          <input type="file" multiple name="photos[]" />        </p>        <p>          <input                       type="checkbox"            name="vehicle[]"            value="Bike" />          <label for="vehicle_bike">Tengo una bicicleta</label><br />          <input                       type="checkbox"            name="vehicle[]"            value="Car" />          <label for="vehicle_car">Tengo un coche</label>        </p>        <p>          Descríbete:<br />          <textarea name="description" cols="50" rows="8"></textarea>        </p>        <p>          <input type="submit" value="Submit" />        </p>      </fieldset>    </form>  </body></html>

Para probar esto, cree una página llamadaregister.php (que es laque se encuentra en el atributoaction de estos formularios de muestra),y ponga lo siguiente contenidominimalista:

php
<?php/* register.php */header("Content-type: text/plain");/*NOTA: Nunca debe usar `print_r()` en scripts de producción, oo datos enviados por el cliente sin sanearlos antes.No sanearlos puede llevar a vulnerabilidades tipo _cross-site scripting_.*/echo ":: Datos recibidos a través de GET ::\n\n";print_r($_GET);echo "\n\n:: Datos recibidos a través de POST ::\n\n";print_r($_POST);echo "\n\n:: Datos recibidos \"sin procesar\" (text/plain encoding) ::\n\n";if (isset($HTTP_RAW_POST_DATA)) { echo $HTTP_RAW_POST_DATA; }echo "\n\n:: Archivos recibidos ::\n\n";print_r($_FILES);

La sintaxis para activar este script es:

js
AJAXSubmit(myForm);

Nota:Este framework utiliza la APIFileReader para transmitir las cargas de archivos. Este es un API reciente y no está implementada en IE9 o inferiores. Por esta razón, la carga sólo en AJAX se considerauna técnica experimental. Si no necesita subir archivos binarios, este framework funciona bien en la mayoría de los navegadores.

Nota:La mejor manera de enviar contenido binario es a través deArrayBuffers oBlobs junto con con el métodosend() y posiblemente el métodoreadAsArrayBuffer() de la APIFileReader. Pero, como el objetivo de este script es trabajar con unstringifiable de datos en bruto, utilizamos el métodosendAsBinary() junto con el métodoreadAsBinaryString() de la APIFileReader. Por lo tanto, el script anterior tiene sentido sólo cuando se trata de archivos pequeños. Si no tiene intención de de cargar contenido binario, considere utilizar la APIFormData.

Nota:El método no estándarsendAsBinary se considera obsoleto a partir de Gecko 31 (Firefox 31 / Thunderbird 31 / SeaMonkey 2.28) y se eliminará pronto. En su lugar se puede utilizar el método estándarsend(Blob data).

Uso de los objetos FormData

El constructorFormData permite recopilar unconjunto de pares clave/valor para enviarlos medianteXMLHttpRequest. Su uso principal es paraenviar datos de formularios, pero también puede utilizarse independientemente de un formulario para transmitirdatos clave del usuario. Los datos transmitidos tienen el mismo formato que el métododel formulario para enviar los datos, si el tipo de codificación del formulario se establece como"multipart/form-data". Los objetos FormData pueden utilizarse de varias maneras con un métodoXMLHttpRequest. Para ver ejemplos y explicaciones de cómo se puede utilizarFormData con XMLHttpRequests, consulte la secciónUtilizando objetos FormData.Para fines didácticos aquí hayunatraducción delejemplo anterior transformado para usar laAPIFormData. Nótese la brevedad del código:

html
<!doctype html><html>  <head>    <meta http-equiv="Content-Type" charset="UTF-8" />    <title>Envío de formularios con FormData &ndash; MDN</title>    <script>      "use strict";      function ajaxSuccess() {        console.log(this.responseText);      }      function AJAXSubmit(oFormElement) {        if (!oFormElement.action) {          return;        }        var oReq = new XMLHttpRequest();        oReq.onload = ajaxSuccess;        if (oFormElement.method.toLowerCase() === "post") {          oReq.open("post", oFormElement.action);          oReq.send(new FormData(oFormElement));        } else {          var oField,            sFieldType,            nFile,            sSearch = "";          for (var nItem = 0; nItem < oFormElement.elements.length; nItem++) {            oField = oFormElement.elements[nItem];            if (!oField.hasAttribute("name")) {              continue;            }            sFieldType =              oField.nodeName.toUpperCase() === "INPUT" &&              oField.hasAttribute("type")                ? oField.getAttribute("type").toUpperCase()                : "TEXT";            if (sFieldType === "FILE") {              for (                nFile = 0;                nFile < oField.files.length;                sSearch +=                  "&" +                  escape(oField.name) +                  "=" +                  escape(oField.files[nFile++].name)              );            } else if (              (sFieldType !== "RADIO" && sFieldType !== "CHECKBOX") ||              oField.checked            ) {              sSearch += "&" + escape(oField.name) + "=" + escape(oField.value);            }          }          oReq.open(            "get",            oFormElement.action.replace(              /(?:\?.*)?$/,              sSearch.replace(/^&/, "?"),            ),            true,          );          oReq.send(null);        }      }    </script>  </head>  <body>    <h1>Envío de formularios con FormData</h1>    <h2>Utilizando el método GET</h2>    <form      action="register.php"      method="get"      onsubmit="AJAXSubmit(this); return false;">      <fieldset>        <legend>Ejemplo de registro</legend>        <p>          Nombre: <input type="text" name="firstname" /><br />          Apellido: <input type="text" name="lastname" />        </p>        <p>          <input type="submit" value="Submit" />        </p>      </fieldset>    </form>    <h2>Utilizando el método POST</h2>    <h3>Enctype: application/x-www-form-urlencoded (por defecto)</h3>    <form      action="register.php"      method="post"      onsubmit="AJAXSubmit(this); return false;">      <fieldset>        <legend>Ejemplo de registro</legend>        <p>          Nombre: <input type="text" name="firstname" /><br />          Apellido: <input type="text" name="lastname" />        </p>        <p>          <input type="submit" value="Submit" />        </p>      </fieldset>    </form>    <h3>Enctype: text/plain</h3>    <p>La codificación text/plain no está permitida en la API de FormData.</p>    <h3>Enctype: multipart/form-data</h3>    <form      action="register.php"      method="post"      enctype="multipart/form-data"      onsubmit="AJAXSubmit(this); return false;">      <fieldset>        <legend>Ejemplo de subida</legend>        <p>          Nombre: <input type="text" name="firstname" /><br />          Apellido: <input type="text" name="lastname" /><br />          Sexo:          <input type="radio" name="sex" value="male" />          <label for="sex_male">Hombre</label>          <input type="radio" name="sex" value="female" />          <label for="sex_female">Mujer</label><br />          Contraseña: <input type="password" name="secret" /><br />          ¿Qué prefieres?:          <select name="image_type">            <option>Libros</option>            <option>Cine</option>            <option>TV</option>          </select>        </p>        <p>          Envía tus fotos:          <input type="file" multiple name="photos[]" />        </p>        <p>          <input                       type="checkbox"            name="vehicle[]"            value="Bike" />          <label for="vehicle_bike">Tengo una bicicleta</label><br />          <input                       type="checkbox"            name="vehicle[]"            value="Car" />          <label for="vehicle_car">Tengo un coche</label>        </p>        <p>          Descríbete:<br />          <textarea name="description" cols="50" rows="8"></textarea>        </p>        <p>          <input type="submit" value="Submit" />        </p>      </fieldset>    </form>  </body></html>

Nota:Como hemos dicho, los objetosFormData no son objetosstringifiable. Si quieres transformar en string los datos enviados, utilizael ejemplo anterior enpuro-AJAX. Tenga en cuenta también que, aunque en este ejemplo hay algunos camposfile<input>,cuando se envía un formulario a través de la APIFormData tampoco es necesario utilizar la APIFileReader: los archivos se cargan y suben automáticamente.

Obtener la fecha de la última modificación

js
function getHeaderTime() {  console.log(    this.getResponseHeader("Last-Modified"),  ); /* Una fecha GMTString válida o null */}var oReq = new XMLHttpRequest();oReq.open(  "HEAD" /* ¡utiliza HEAD si sólo necesitas las cabeceras! */,  "yourpage.html",);oReq.onload = getHeaderTime;oReq.send();

Hacer algo cuando cambia la última fecha de modificación

Vamos a crear dos funciones:

js
function getHeaderTime() {  var nLastVisit = parseFloat(    window.localStorage.getItem("lm_" + this.filepath),  );  var nLastModified = Date.parse(this.getResponseHeader("Last-Modified"));  if (isNaN(nLastVisit) || nLastModified > nLastVisit) {    window.localStorage.setItem("lm_" + this.filepath, Date.now());    isFinite(nLastVisit) && this.callback(nLastModified, nLastVisit);  }}function ifHasChanged(sURL, fCallback) {  var oReq = new XMLHttpRequest();  oReq.open(    "HEAD" /* ¡utiliza HEAD - ¡sólo necesitamos las cabeceras! */,    sURL,  );  oReq.callback = fCallback;  oReq.filepath = sURL;  oReq.onload = getHeaderTime;  oReq.send();}

Y para probar:

js
/* Probemos el fichero "yourpage.html"... */ifHasChanged("yourpage.html", function (nModified, nVisit) {  console.log(    "¡La página '" +      this.filepath +      "' ha cambiado el " +      new Date(nModified).toLocaleString() +      "!",  );});

Si quieres sabersila página actual ha cambiado,por favor, lee el artículo sobredocument.lastModified.

Cross-site XMLHttpRequest

Los navegadores modernos admiten las peticiones cross-site implementando el estándarRecursos compartidos de origen-cruzado (CORS).Siempre que el servidor esté configurado para permitir las peticiones desde el origen de su aplicación web,XMLHttpRequest funcionará. En caso contrario, se lanzará una excepciónINVALID_ACCESS_ERR.

Evitar la caché

Un enfoque compatible con todos los navegadores para evitar la caché es añadir una marca de tiempo aa la URL, asegurándose de incluir un "?" o "&" según corresponda. Por ejemplo:

http://foo.com/bar.html -> http://foo.com/bar.html?12345http://foo.com/bar.html?foobar=baz -> http://foo.com/bar.html?foobar=baz&12345

Como la caché local se indexa por URL, esto hace que cada petición sea única, por lo quesalta la caché.

Puedes ajustar automáticamente las URLs usando el siguiente código:

js
var oReq = new XMLHttpRequest();oReq.open("GET", url + (/\?/.test(url) ? "&" : "?") + new Date().getTime());oReq.send(null);

Seguridad

La manera recomendada para habilitar el cross-site scripting es utilizar la cabeceracabecera HTTPAccess-Control-Allow-Origin en la respuesta alXMLHttpRequest.

XMLHttpRequests que se detienen

Si concluye con una XMLHttpRequest que recibestatus=0 ystatusText=null, significa que no se ha permitido realizar la petición. EraUNSENT.Una causa probable de esto es cuando elorigenXMLHttpRequest (en la creación de la XMLHttpRequest) ha cambiado cuando el XMLHttpRequestes posterior aopen(). Este caso puede darse, por ejemplo, cuando se tiene unXMLHttpRequest que se dispara en un evento onunload para una ventana, el esperadoXMLHttpRequest se crea cuando la ventana a cerrar sigue ahí, y finalmenteenviar la petición (en otras palabras,open()) cuando esta ventana ha perdido su focoy otra ventana toma el foco. La forma más eficaz de evitar este problema eses establecer una escucha en el eventoactivate de la nueva ventana que se activa una vez que laventana terminada tenga su eventounload disparado.

Workers

EstableceroverrideMimeType no funciona desde unWorker. VerError 678057 en Firefox para más detalles. Otros navegadores pueden manejar esto de manera diferente.

Especificaciones

Specification
XMLHttpRequest
# interface-xmlhttprequest

Compatibilidad con navegadores

Véase también

Help improve MDN

Learn how to contribute.

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp