Оригинал запроса Ajax, необходимый для собеседования

JavaScript Ajax

Объект XMLHttpRequest

Введение

Связь между браузером и сервером использует протокол HTTP. Когда пользователь вводит URL-адрес в адресной строке браузера или отправляет контент на сервер через веб-форму, браузер отправляет HTTP-запрос на сервер.

В 1999 году Microsoft выпустила версию 5.0 браузера IE, в которой впервые появилась новая функция: разрешение JavaScript-скриптам инициировать HTTP-запросы к серверу. В то время эта функция оставалась незамеченной и не привлекала широкого внимания до выпуска Gmail в 2004 году и выпуска Google Maps в 2005 году. В феврале 2005 года впервые было официально предложено слово AJAX — это аббревиатура от Asynchronous JavaScript and XML, которая относится к асинхронному обмену данными JavaScript, который получает XML-документы с сервера и извлекает из них данные, а затем обновляет их. соответствующую часть текущей веб-страницы. Нет необходимости обновлять всю страницу. Позже слово AJAX стало синонимом связи HTTP, инициируемой скриптом JavaScript, то есть, если связь инициируется сценарием, ее можно назвать связью AJAX. W3C также опубликовал свой международный стандарт в 2006 году.

В частности, AJAX включает следующие шаги.

  1. Создайте экземпляр XMLHttpRequest
  2. сделать HTTP-запрос
  3. Принимающий сервер возвращает данные
  4. Обновить веб-данные

Подводя итог, это предложение, AJAX через роднойXMLHttpRequestОбъект отправляет HTTP-запрос, а затем обрабатывает его после получения данных, возвращенных сервером. Теперь сервер возвращает данные в формате JSON, формат XML устарел, но название AJAX стало нарицательным, а буквальное значение исчезло.

XMLHttpRequestОбъекты — это основной интерфейс AJAX для связи между браузером и сервером. Хотя имя имеетXMLа такжеHttpНа самом деле он может использовать различные протоколы (такие какfileилиftp), отправка данных в любом формате (включая строковый и двоичный).

XMLHttpRequestсам по себе является конструктором и может использоваться сnewкоманда для создания экземпляра. У него нет никаких параметров.

var xhr = new XMLHttpRequest();

После создания экземпляра вы можете использоватьopen()Метод указывает некоторые детали установки HTTP-соединения.

xhr.open('GET', 'http://www.example.com/page.php', true);

Приведенный выше код указывает на использование метода GET для установления соединения с указанным URL-адресом сервера. третий параметрtrue, что указывает на то, что запрос является асинхронным.

Затем укажите функцию обратного вызова для контроля состояния связи (readyStateсвойства) меняется.

xhr.onreadystatechange = handleStateChange;

function handleStateChange() {
  // ...
}

В приведенном выше коде один разXMLHttpRequestКогда состояние экземпляра изменяется, вызывается функция слушателя.handleStateChange

последнее использованиеsend()метод, который фактически делает запрос.

xhr.send(null);

В приведенном выше кодеsend()Параметрыnull, что указывает на отсутствие тела данных при отправке запроса. Если вы отправляете POST-запрос, вам нужно указать здесь тело данных.

После получения данных, возвращаемых сервером, AJAX не обновляет всю веб-страницу, а обновляет только соответствующую часть веб-страницы, чтобы не прерывать действия пользователя.

Обратите внимание, что AJAX может отправлять HTTP-запросы только на URL-адреса того же происхождения (с тем же протоколом, доменным именем и портом).

НижеXMLHttpRequestПолный пример простого использования объектов.

var xhr = new XMLHttpRequest();

xhr.onreadystatechange = function(){
  // 通信成功时,状态值为4
  if (xhr.readyState === 4){
    if (xhr.status === 200){
      console.log(xhr.responseText);
    } else {
      console.error(xhr.statusText);
    }
  }
};

xhr.onerror = function (e) {
  console.error(xhr.statusText);
};

xhr.open('GET', '/endpoint', true);
xhr.send(null);

Свойства экземпляра XMLHttpRequest

XMLHttpRequest.readyState

XMLHttpRequest.readyStateВозвращает целое число, представляющее текущее состояние объекта экземпляра. Это свойство доступно только для чтения. Он может возвращать следующие значения.

  • 0, что указывает на то, что экземпляр XMLHttpRequest был сгенерирован, ноopen()Метод еще не вызывался.
  • 1 с указаниемopen()был вызван метод, но экземплярsend()Метод еще не был вызван, вы все еще можете использовать экземпляр экземпляраsetRequestHeader()метод, который устанавливает информацию заголовка HTTP-запроса.
  • 2, указать примерsend()Метод был вызван, и возвращенные сервером заголовки и коды состояния получены.
  • 3, что указывает на то, что тело данных (часть тела) принимается с сервера. В этот момент, если экземплярresponseTypeсвойство равноtextили пустая строка,responseTextАтрибут будет содержать часть полученной информации.
  • 4. Указывает, что данные, возвращенные сервером, были полностью получены или текущий прием не удался.

В процессе связи всякий раз, когда изменяется состояние объекта-экземпляра, егоreadyStateСтоимость имущества изменится. Каждый раз, когда это значение изменяется,readyStateChangeмероприятие.

var xhr = new XMLHttpRequest();

if (xhr.readyState === 4) {
  // 请求结束,处理服务器返回的数据
} else {
  // 显示提示“加载中……”
}

В приведенном выше кодеxhr.readyStateравный4, указывая на то, что HTTP-запрос, сделанный сценарием, выполнен. В других случаях это означает, что HTTP-запрос все еще выполняется.

XMLHttpRequest.onreadystatechange

XMLHttpRequest.onreadystatechangeСвойство указывает на функцию прослушивателя.readystatechangeКогда происходит событие (экземплярreadyStateизменение свойства), это свойство будет выполнено.

Кроме того, если вы используете экземплярabort()метод, завершающий запрос XMLHttpRequest, также вызываетreadyStateизменения свойств, что приводит к вызовуXMLHttpRequest.onreadystatechangeАтрибуты.

Ниже приведен пример.

var xhr = new XMLHttpRequest();
xhr.open( 'GET', 'http://example.com' , true );
xhr.onreadystatechange = function () {
  if (xhr.readyState !== 4 || xhr.status !== 200) {
    return;
  }
  console.log(xhr.responseText);
};
xhr.send();

XMLHttpRequest.response

XMLHttpRequest.responseАтрибут представляет тело данных, возвращаемое сервером (т. е. часть тела ответа HTTP). Это может быть любой тип данных, такой как строка, объект, двоичный объект и т. д. Конкретный тип определяетсяXMLHttpRequest.responseTypeатрибутивное решение. Свойство XMLHttpRequest.response доступно только для чтения.

Если запрос не удался или данные неполные, это свойство равноnull. но еслиresponseTypeсвойство равноtextили пустая строка, до того как запрос не закончился (readyStateравно 3 этапам),responseСвойства содержат частичные данные, возвращенные сервером.

var xhr = new XMLHttpRequest();

xhr.onreadystatechange = function () {
  if (xhr.readyState === 4) {
    handler(xhr.response);
  }
}

XMLHttpRequest.responseType

XMLHttpRequest.responseTypeСвойство представляет собой строку, представляющую тип данных, возвращаемых сервером. Это свойство доступно для записи и может быть вызваноopen()После метода вызовитеsend()Перед методом установите значение этого свойства, чтобы указать браузеру, как интерпретировать возвращенные данные. еслиresponseTypeУстановите пустую строку, которая эквивалентна значению по умолчанию.text.

XMLHttpRequest.responseTypeСвойства могут быть равны следующим значениям.

  • "" (пустая строка): эквивалентноtext, указывающее, что сервер возвращает текстовые данные.
  • "arraybuffer": объект ArrayBuffer, указывающий, что сервер возвращает двоичный массив.
  • "blob": объект Blob, указывающий, что сервер возвращает двоичный объект.
  • "document": объект документа, указывающий, что сервер возвращает объект документа.
  • "json": объект JSON.
  • "текст": строка.

Среди вышеперечисленных типовtextШрифт подходит для большинства случаев, и с ним удобно работать непосредственно с текстом.documentЭтот тип подходит для возврата документов HTML/XML, а это означает, что для тех веб-сайтов, которые открывают CORS, вы можете напрямую использовать Ajax для обхода веб-страницы, а затем напрямую выполнять операции DOM с захваченными данными без разбора строки HTML.blobТип подходит для чтения двоичных данных, таких как файлы изображений.

var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
xhr.responseType = 'blob';

xhr.onload = function(e) {
  if (this.status === 200) {
    var blob = new Blob([xhr.response], {type: 'image/png'});
    // 或者
    var blob = xhr.response;
  }
};

xhr.send();

Если это свойство установлено вArrayBuffer, вы можете обрабатывать двоичные данные как массив.

var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
xhr.responseType = 'arraybuffer';

xhr.onload = function(e) {
  var uInt8Array = new Uint8Array(this.response);
  for (var i = 0, len = uInt8Array.length; i < len; ++i) {
    // var byte = uInt8Array[i];
  }
};

xhr.send();

Если это свойство установлено вjson, браузер автоматически вызовет возвращенные данныеJSON.parse()метод. То есть изxhr.responseсвойства (обратите внимание, неxhr.responseTextсвойство) вместо текста вы получаете объект JSON.

XMLHttpRequest.responseText

XMLHttpRequest.responseTextСвойство возвращает строку, полученную от сервера, это свойство доступно только для чтения. Это свойство не будет содержать полные данные, пока не будет получен HTTP-запрос.

var xhr = new XMLHttpRequest();
xhr.open('GET', '/server', true);

xhr.responseType = 'text';
xhr.onload = function () {
  if (xhr.readyState === 4 && xhr.status === 200) {
    console.log(xhr.responseText);
  }
};

xhr.send(null);

XMLHttpRequest.responseXML

XMLHttpRequest.responseXMLСвойство возвращает объект документа HTML или XML, полученный от сервера, и доступен только для чтения. Если запрос был неудачным или полученные данные не удалось проанализировать как XML или HTML, этот атрибут равенnull.

Условием для того, чтобы этот атрибут вступил в силу, является то, что ответ HTTPContent-TypeИнформация о головке равнаtext/xmlилиapplication/xml. Для этого необходимо, чтобы перед отправкой запросаXMLHttpRequest.responseTypeсвойство, которое должно быть установленоdocument. если ответ HTTPContent-Typeинформация заголовка не равнаtext/xmlа такжеapplication/xml, но хочуresponseXMLПолучить данные (то есть разобрать данные по формату DOM), затем нужно вручную вызватьXMLHttpRequest.overrideMimeType()метод принудительного разбора XML.

Данные, полученные с помощью этого свойства, представляют собой непосредственно анализируемое дерево DOM документа.

var xhr = new XMLHttpRequest();
xhr.open('GET', '/server', true);

xhr.responseType = 'document';
xhr.overrideMimeType('text/xml');

xhr.onload = function () {
  if (xhr.readyState === 4 && xhr.status === 200) {
    console.log(xhr.responseXML);
  }
};

xhr.send(null);

XMLHttpRequest.responseURL

XMLHttpRequest.responseURLСвойство представляет собой строку, представляющую URL-адрес сервера, отправляющего данные.

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/test', true);
xhr.onload = function () {
  // 返回 http://example.com/test
  console.log(xhr.responseURL);
};
xhr.send(null);

Обратите внимание, что значение этого свойства такое же, какopen()URL-адрес запроса, указанный методом, не обязательно совпадает. Если на стороне сервера происходит переход, это свойство возвращает последний URL-адрес, фактически вернувший данные. Кроме того, если исходный URL-адрес содержал привязку (фрагмент), это свойство удаляет привязку.

XMLHttpRequest.status, XMLHttpRequest.statusText

XMLHttpRequest.statusСвойство возвращает целое число, представляющее код состояния HTTP, которым ответил сервер. Вообще говоря, если связь успешна, этот код состояния равен 200; если сервер не возвращает код состояния, то это свойство по умолчанию равно 200. Прежде чем сделать запрос, имущество0. Это свойство доступно только для чтения.

  • 200, ок, доступ нормальный
  • 301, переехал навсегда
  • 302, Временно переехал
  • 304, не изменено, не изменено
  • 307, Временная переадресация, временная переадресация
  • 401, Неавторизованный, неавторизованный
  • 403, Запрещено, Запрещено
  • 404, Not Found, указанный URL не найден
  • 500, Внутренняя ошибка сервера, произошла ошибка сервера

По сути, есть только коды состояния 2xx и 304, указывающие на то, что сервер возвращает нормальный статус.

if (xhr.readyState === 4) {
  if ( (xhr.status >= 200 && xhr.status < 300)
    || (xhr.status === 304) ) {
    // 处理服务器的返回数据
  } else {
    // 出错
  }
}

XMLHttpRequest.statusTextСвойство возвращает строку, представляющую запрос состояния, отправленный сервером. отличный отstatusсвойство, которое содержит всю информацию о состоянии, такую ​​как «ОК» и «Не найдено». до того, как запрос будет отправлен (т.е. вызовopen()Перед методом) значение свойства является пустой строкой; если сервер не возвращает приглашение состояния, значение по умолчанию это атрибут «ОК». Это свойство только для чтения.

XMLHttpRequest.timeout, XMLHttpRequestEventTarget.ontimeout

XMLHttpRequest.timeoutСвойство возвращает целое число, указывающее количество миллисекунд, по истечении которых запрос автоматически завершится, если результата по-прежнему нет. Если это свойство равно 0, это означает, что ограничения по времени нет.

XMLHttpRequestEventTarget.ontimeoutСвойство используется для установки функции прослушивателя, которая будет выполняться, если произойдет событие тайм-аута.

Ниже приведен пример.

var xhr = new XMLHttpRequest();
var url = '/server';

xhr.ontimeout = function () {
  console.error('The request for ' + url + ' timed out.');
};

xhr.onload = function() {
  if (xhr.readyState === 4) {
    if (xhr.status === 200) {
      // 处理服务器返回的数据
    } else {
      console.error(xhr.statusText);
    }
  }
};

xhr.open('GET', url, true);
// 指定 10 秒钟超时
xhr.timeout = 10 * 1000;
xhr.send(null);

свойство прослушивателя событий

Объект XMLHttpRequest может указывать функции прослушивателя для следующих событий.

  • XMLHttpRequest.onloadstart: функция прослушивания события loadstart (запрос HTTP отправлен)
  • XMLHttpRequest.onprogress: функция прослушивания для события прогресса (отправка и загрузка данных)
  • XMLHttpRequest.onabort: событие прерывания (запрос прерван, например, вызванный пользователемabort()метод) функция слушателя
  • XMLHttpRequest.onerror: функция прослушивания события ошибки (сбой запроса)
  • XMLHttpRequest.onload: функция прослушивания события загрузки (запрос выполнен успешно)
  • XMLHttpRequest.ontimeout: функция прослушивания события тайм-аута (указанный пользователем лимит времени превышен, и запрос не был выполнен)
  • XMLHttpRequest.onloadend: функция прослушивания события loadend (запрос выполнен независимо от успеха или неудачи)

Ниже приведен пример.

xhr.onload = function() {
 var responseText = xhr.responseText;
 console.log(responseText);
 // process the response.
};

xhr.onabort = function () {
  console.log('The request was aborted');
};

xhr.onprogress = function (event) {
  console.log(event.loaded);
  console.log(event.total);
};

xhr.onerror = function() {
  console.log('There was an error!');
};

progressФункция прослушивателя событий имеет параметр объекта события, который имеет три свойства:loadedсвойство возвращает количество данных, которые были переданы,totalсвойство возвращает общий объем данных,lengthComputableСвойство возвращает логическое значение, указывающее, можно ли рассчитать ход загрузки. Из всех этих функций слушателя толькоprogressФункция слушателя события имеет параметры, а другие функции не имеют параметров.

Обратите внимание, что в случае сетевой ошибки (например, если сервер недоступен),onerrorСобытие не может получить сообщение об ошибке. То есть может не быть объекта ошибки, поэтому он может отображать только сообщение об ошибке.

XMLHttpRequest.withCredentials

XMLHttpRequest.withCredentialsАтрибут представляет собой логическое значение, указывающее, будет ли информация о пользователе (такая как файлы cookie и информация заголовка HTTP аутентификации) включаться в запрос во время междоменных запросов.false, то есть кexample.comПри создании кросс-оригинального запроса он не отправляетсяexample.comФайлы cookie, установленные на этом компьютере (если есть).

Если вам нужно отправлять файлы cookie для междоменных запросов AJAX, вам необходимоwithCredentialsсвойство установлено наtrue. Обратите внимание, что для гомологичных запросов не требуется устанавливать это свойство.

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);

Чтобы это свойство вступило в силу, сервер должен явно вернутьAccess-Control-Allow-Credentialsэта информация заголовка.

Access-Control-Allow-Credentials: true

withCredentialsЕсли атрибут включен, междоменный запрос не только отправит файл cookie, но и установит файл cookie, указанный удаленным хостом. Верно и обратное, еслиwithCredentialsЕсли атрибут не включен, браузер будет игнорировать междоменный запрос AJAX, даже если он явно просит браузер установить файл cookie.

Обратите внимание, что сценарии всегда придерживаются политики одного и того же источника и не могут быть загружены изdocument.cookieИли прочитайте междоменный файл cookie в информации заголовка HTTP-ответа,withCredentialsСвойства на это не влияют.

XMLHttpRequest.upload

XMLHttpRequest может не только отправлять запросы, но и файлы, то есть загружать файлы AJAX. После отправки файла черезXMLHttpRequest.uploadСвойства могут получить объект, и, наблюдая за этим объектом, вы можете узнать о ходе загрузки. Основной метод — отслеживать различные события этого объекта: loadstart, loadend, load, abort, error, progress, timeout.

Предположим, есть<progress>элемент.

<progress min="0" max="100" value="0">0% complete</progress>

Когда файл загружен, даuploadназначение атрибутаprogressФункция прослушивания событий, вы можете получить ход загрузки.

function upload(blobOrFile) {
  var xhr = new XMLHttpRequest();
  xhr.open('POST', '/server', true);
  xhr.onload = function (e) {};

  var progressBar = document.querySelector('progress');
  xhr.upload.onprogress = function (e) {
    if (e.lengthComputable) {
      progressBar.value = (e.loaded / e.total) * 100;
      // 兼容不支持 <progress> 元素的老式浏览器
      progressBar.textContent = progressBar.value;
    }
  };

  xhr.send(blobOrFile);
}

upload(new Blob(['hello world'], {type: 'text/plain'}));

Методы экземпляра XMLHttpRequest

XMLHttpRequest.open()

XMLHttpRequest.open()Этот метод используется для указания параметров HTTP-запроса или для инициализации объекта экземпляра XMLHttpRequest. Он может принимать в общей сложности пять параметров.

void open(
   string method,
   string url,
   optional boolean async,
   optional string user,
   optional string password
);
  • method: представляет метод HTTP-глагола, напримерGET,POST,PUT,DELETE,HEADЖдать.
  • url: указывает запрос на отправку целевого URL.
  • async: логическое значение, указывающее, является ли запрос асинхронным, по умолчаниюtrue. Если установленоfalse,ноsend()Метод не перейдет к следующему шагу, пока не получит результат, возвращенный сервером. Этот параметр является необязательным. Поскольку синхронные запросы AJAX приводят к тому, что браузер перестает отвечать на запросы, многие браузеры запретили его использование в основном потоке и разрешили использовать его только в Worker. Поэтому этот параметр легко не должен быть установлен наfalse.
  • user: указывает имя пользователя, используемое для аутентификации, по умолчанию — пустая строка. Этот параметр является необязательным.
  • password: указывает пароль, используемый для аутентификации, по умолчанию — пустая строка. Этот параметр является необязательным.

Обратите внимание, что если вы использовалиopen()AJAX-запрос метода, повторное использование этого метода эквивалентно вызовуabort(), который завершает запрос.

Ниже приведен пример отправки POST-запроса.

var xhr = new XMLHttpRequest();
xhr.open('POST', encodeURI('someURL'));

XMLHttpRequest.send()

XMLHttpRequest.send()метод используется для фактического выполнения HTTP-запроса. Его параметры необязательны. Если нет параметров, это означает, что HTTP-запрос имеет только один URL и не имеет тела данных. Типичный пример — GET-запрос, если он имеет параметры, это означает, что помимо информации заголовка, он также содержит информацию, содержащую определенные данные body, типичным примером является POST-запрос.

Ниже приведен пример GET-запроса.

var xhr = new XMLHttpRequest();
xhr.open('GET',
  'http://www.example.com/?id=' + encodeURIComponent(id),
  true
);
xhr.send(null);

В приведенном выше кодеGETПараметры запроса, добавленные к URL-адресу в виде строки запроса.

Ниже приведен пример отправки POST-запроса.

var xhr = new XMLHttpRequest();
var data = 'email='
  + encodeURIComponent(email)
  + '&password='
  + encodeURIComponent(password);

xhr.open('POST', 'http://www.example.com', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send(data);

Обратите внимание, что все события прослушивателя XMLHttpRequest должныsend()Устанавливается перед вызовом метода.

sendПараметр метода — это данные для отправки. В качестве его параметров могут использоваться данные в различных форматах.

void send();
void send(ArrayBufferView data);
void send(Blob data);
void send(Document data);
void send(String data);
void send(FormData data);

еслиsend()Отправьте объект DOM, данные будут сериализованы перед отправкой. При отправке двоичных данных лучше отправитьArrayBufferViewилиBlobобъект, что позволяет загружать файлы через Ajax.

Ниже приведен пример отправки данных формы.FormDataОбъекты можно использовать для создания данных формы.

var formData = new FormData();

formData.append('username', '张三');
formData.append('email', 'zhangsan@example.com');
formData.append('birthDate', 1940);

var xhr = new XMLHttpRequest();
xhr.open('POST', '/register');
xhr.send(formData);

В приведенном выше кодеFormDataобъект создает данные формы, а затем используетsend()способ отправки. Это имеет тот же эффект, что и отправка данных формы ниже.

<form id='registration' name='registration' action='/register'>
  <input type='text' name='username' value='张三'>
  <input type='email' name='email' value='zhangsan@example.com'>
  <input type='number' name='birthDate' value='1940'>
  <input type='submit' onclick='return sendForm(this.form);'>
</form>

В следующем примере используетсяFormDataОбъект обрабатывает данные формы перед их отправкой.

function sendForm(form) {
  var formData = new FormData(form);
  formData.append('csrf', 'e69a18d7db1286040586e6da1950128c');

  var xhr = new XMLHttpRequest();
  xhr.open('POST', form.action, true);
  xhr.onload = function() {
    // ...
  };
  xhr.send(formData);

  return false;
}

var form = document.querySelector('#registration');
sendForm(form);

XMLHttpRequest.setRequestHeader()

XMLHttpRequest.setRequestHeader()Этот метод используется для установки информации заголовка HTTP-запроса, отправляемого браузером. Метод должен бытьopen()Позже,send()звонил раньше. Если этот метод вызывается несколько раз для установки одного и того же поля, значения каждого вызова будут объединены в одно значение и отправлены.

Метод принимает два параметра. Первый параметр — это строка, представляющая имя поля информации заголовка, а второй параметр — это значение поля.

xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Content-Length', JSON.stringify(data).length);
xhr.send(JSON.stringify(data));

Приведенный выше код сначала устанавливает информацию заголовкаContent-Type, что означает отправку данных в формате JSON, затем установитеContent-Length, указав длину данных; наконец, отправьте данные JSON.

XMLHttpRequest.overrideMimeType()

XMLHttpRequest.overrideMimeType()Этот метод используется для указания типа MIME, переопределяя реальный тип MIME, возвращаемый сервером, чтобы браузер мог обрабатывать его по-другому. Например, тип данных, возвращаемый сервером,text/xml, по разным причинам браузер не может выполнить синтаксический анализ и сообщает об ошибке, а данные не могут быть получены в настоящее время. Чтобы получить необработанные данные, мы можем изменить тип MIME наtext/plain, чтобы браузер не разбирал его автоматически, чтобы мы могли получить исходный текст.

xhr.overrideMimeType('text/plain')

Обратите внимание, что этот метод должен бытьsend()метод вызывается раньше.

Изменение типа данных, возвращаемых сервером, не является методом, который следует использовать в обычных обстоятельствах. Если вы хотите, чтобы сервер возвращал указанный тип данных, вы можете использоватьresponseTypeАтрибут сообщает серверу, как в примере ниже. Используйте только в том случае, если сервер не может вернуть определенный тип данныхoverrideMimeType()метод.

var xhr = new XMLHttpRequest();
xhr.onload = function(e) {
  var arraybuffer = xhr.response;
  // ...
}
xhr.open('GET', url);
xhr.responseType = 'arraybuffer';
xhr.send();

XMLHttpRequest.getResponseHeader()

XMLHttpRequest.getResponseHeader()Метод возвращает значение указанного поля в информации заголовка HTTP.Если сервер не получил ответа или указанного поля не существует, возвращаетnull. Аргументы этого метода не чувствительны к регистру.

function getHeaderTime() {
  console.log(this.getResponseHeader("Last-Modified"));
}

var xhr = new XMLHttpRequest();
xhr.open('HEAD', 'yourpage.html');
xhr.onload = getHeaderTime;
xhr.send();

Если есть несколько полей с одинаковым именем, их значения будут объединены в строку, и каждое поле будет разделено «запятой+пробелом».

XMLHttpRequest.getAllResponseHeaders()

XMLHttpRequest.getAllResponseHeaders()Метод возвращает строку, представляющую все заголовки HTTP, отправленные сервером. Формат представляет собой строку, используемую между каждой информацией заголовка.CRLFРазделение (возврат каретки + перевод строки), если ответ от сервера не получен, это свойствоnull. Если возникает сетевая ошибка, это свойство представляет собой пустую строку.

var xhr = new XMLHttpRequest();
xhr.open('GET', 'foo.txt', true);
xhr.send();

xhr.onreadystatechange = function () {
  if (this.readyState === 4) {
    var headers = xhr.getAllResponseHeaders();
  }
}

Приведенный выше код используется для получения всей информации заголовка, возвращаемой сервером. Это может быть строка, подобная следующей.

date: Fri, 08 Dec 2017 21:04:30 GMT\r\n
content-encoding: gzip\r\n
x-content-type-options: nosniff\r\n
server: meinheld/0.6.1\r\n
x-frame-options: DENY\r\n
content-type: text/html; charset=utf-8\r\n
connection: keep-alive\r\n
strict-transport-security: max-age=63072000\r\n
vary: Cookie, Accept-Encoding\r\n
content-length: 6502\r\n
x-xss-protection: 1; mode=block\r\n

Затем обработайте эту строку.

var arr = headers.trim().split(/[\r\n]+/);
var headerMap = {};

arr.forEach(function (line) {
  var parts = line.split(': ');
  var header = parts.shift();
  var value = parts.join(': ');
  headerMap[header] = value;
});

headerMap['content-length'] // "6502"

XMLHttpRequest.abort()

XMLHttpRequest.abort()Этот метод используется для завершения сделанного HTTP-запроса. После вызова этого методаreadyStateсобственность становится4,statusсобственность становится0.

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.example.com/page.php', true);
setTimeout(function () {
  if (xhr) {
    xhr.abort();
    xhr = null;
  }
}, 5000);

Приведенный выше код завершает запрос AJAX через 5 секунд после его отправки.

События для экземпляров XMLHttpRequest

событие readyStateChange

readyStateПри изменении значения свойства запускается событие readyStateChange.

мы можем пройтиonReadyStateChangeАтрибут определяет функцию прослушивателя этого события и по-разному обрабатывает разные состояния. особенно когда государство становится4Когда связь успешна, функция обратного вызова может обрабатывать данные, отправленные обратно сервером.

событие прогресса

При загрузке файла сам объект экземпляра XMLHttpRequest иuploadатрибут, естьprogressсобытие, которое будет постоянно возвращать ход загрузки.

var xhr = new XMLHttpRequest();

function updateProgress (oEvent) {
  if (oEvent.lengthComputable) {
    var percentComplete = oEvent.loaded / oEvent.total;
  } else {
    console.log('无法计算进展');
  }
}

xhr.addEventListener('progress', updateProgress);

xhr.open();

событие загрузки, событие ошибки, событие прерывания

Событие загрузки указывает на то, что данные с сервера были получены, событие ошибки указывает на то, что запрос был выполнен неправильно, а событие прерывания указывает на то, что запрос был прерван (например, пользователь отменяет запрос).

var xhr = new XMLHttpRequest();

xhr.addEventListener('load', transferComplete);
xhr.addEventListener('error', transferFailed);
xhr.addEventListener('abort', transferCanceled);

xhr.open();

function transferComplete() {
  console.log('数据接收完毕');
}

function transferFailed() {
  console.log('数据接收出错');
}

function transferCanceled() {
  console.log('用户取消接收');
}

событие завершения загрузки

abort,loadа такжеerrorЭти три мероприятия будут сопровождатьсяloadendСобытие, указывающее на завершение запроса, но неизвестно, был ли он успешным.

xhr.addEventListener('loadend', loadEnd);

function loadEnd(e) {
  console.log('请求结束,状态未知');
}

событие тайм-аута

Если сервер не вернул результат по истечении указанного времени, будет запущено событие тайм-аута Конкретные примеры см.timeoutРаздел свойств.

Navigator.sendBeacon()

Когда пользователь удаляет веб-страницу, иногда необходимо отправить некоторые данные на сервер. Естественный способ состоит в том, чтобыunloadсобытие илиbeforeunloadВнутри функции прослушивателя событий используйтеXMLHttpRequestОбъект отправляет данные. Однако это не очень надежно, посколькуXMLHttpRequestОбъект отправляется асинхронно, и, вероятно, когда он будет отправлен, страница уже будет выгружена, что приведет к отмене или сбою отправки.

РешениеunloadНа всякий случай добавьте несколько трудоемких операций синхронизации. Это дает достаточно времени для успешной отправки асинхронного AJAX.

function log() {
  let xhr = new XMLHttpRequest();
  xhr.open('post', '/log', true);
  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  xhr.send('foo=bar');
}

window.addEventListener('unload', function(event) {
  log();

  // a time-consuming operation
  for (let i = 1; i < 10000; i++) {
    for (let m = 1; m < 10000; m++) { continue; }
  }
});

В приведенном выше коде применяется двойной цикл, который продлеваетunloadВремя выполнения события, благодаря которому асинхронный AJAX может быть успешно отправлен.

Подобные также могут быть использованыsetTimeout. Ниже приведен пример отслеживания кликов пользователей.

// HTML 代码如下
// <a id="target" href="https://baidu.com">click</a>
const clickTime = 350;
const theLink = document.getElementById('target');

function log() {
  let xhr = new XMLHttpRequest();
  xhr.open('post', '/log', true);
  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  xhr.send('foo=bar');
}

theLink.addEventListener('click', function (event) {
  event.preventDefault();
  log();

  setTimeout(function () {
    window.location.href = theLink.getAttribute('href');
  }, clickTime);
});

Используйте приведенный выше кодsetTimeout, задерживается на 350 миллисекунд перед переходом на страницу, что дает асинхронному AJAX время для выполнения.

Общая проблема этих практик заключается в том, что время выгрузки резко увеличивается, загрузка последующих страниц задерживается, а взаимодействие с пользователем ухудшается.

Чтобы решить эту проблему, браузеры представилиNavigator.sendBeacon()метод. Этот метод по-прежнему отправляет запрос асинхронно, но запрос отделяется от потока текущей страницы как задача процесса браузера, поэтому гарантируется, что данные будут отправлены без задержки процесса удаления.

window.addEventListener('unload', logData, false);

function logData() {
  navigator.sendBeacon('/log', analyticsData);
}

Navigator.sendBeaconМетод принимает два параметра, первый параметр — это URL-адрес целевого сервера, а второй параметр — это отправляемые данные (необязательно), которые могут быть любого типа (строка, объект формы, двоичный объект и т. д.).

navigator.sendBeacon(url, data)

Возвращаемое значение этого метода является логическим значением, а успешно отправленные данныеtrue, иначеfalse.

Метод HTTP для отправки данных с помощью этого метода — POST, который может быть междоменным, подобно данным отправки формы. Он не может указать функцию обратного вызова.

Ниже приведен пример.

// HTML 代码如下
// <body onload="analytics('start')" onunload="analytics('end')">

function analytics(state) {
  if (!navigator.sendBeacon) return;

  var URL = 'http://example.com/analytics';
  var data = 'state=' + state + '&location=' + window.location;
  navigator.sendBeacon(URL, data);
}