Увидев название, некоторые учащиеся могут подумать: «Я использовал
xhr
успешно разместил многоAjax
Я просил, и я достаточно хорошо разбираюсь в его основных операциях. Я думал так же, как и вы, ребята, до недавнего времени я использовалxhr
Когда я наступил на множество ям, я вдруг понял, что знаю недостаточно.xhr
, я знаю только самое основное использование.
Поэтому я решил провести небольшое исследованиеxhr
Но после прочтения многих блогов я не был удовлетворен, поэтому решил внимательно прочитать блог W3C.XMLHttpRequest
стандарт. После прочтения стандарта я почувствовал себя просветленным, и я ощутил ясность, которой у меня никогда не было раньше. Эта статья является ссылкой на W3CXMLHttpRequest
Он основан на стандарте и сочетается с некоторой практической проверкой.
Ajax
а такжеXMLHttpRequest
мы, как правилоAjax
ЭквивалентноXMLHttpRequest
, но при ближайшем рассмотрении оказывается, что это два понятия, принадлежащие к разным измерениям.
Вот что я считаю правильным
Ajax
Более точное объяснение: (взято изwhat is Ajax)
AJAX stands for Asynchronous JavaScript and XML. AJAX is a new technique for creating better, faster, and more interactive web applications with the help of XML, HTML, CSS, and Java Script.AJAX is based on the following open standards:
Browser-based presentation using HTML and Cascading Style Sheets (CSS).
Data is stored in XML format and fetched from the server.
Behind-the-scenes data fetches using XMLHttpRequest objects in the browser.
JavaScript to make everything happen.
Из приведенного выше пояснения можно узнать, что:ajax
является техническим решением, но неновая технология. он опирается на существующиеCSS
/HTML
/Javascript
, а основная зависимость предоставляется браузеромXMLHttpRequest
объект, который позволяет браузеру испускатьHTTP
запросить и получитьHTTP
отклик.
Итак, я резюмирую отношения между ними в одном предложении: мы используемXMLHttpRequest
объект для отправкиAjax
просить.
XMLHttpRequest
история развития
XMLHttpRequest
Сначала это был просто интерфейс, предоставляемый браузером Microsoft. Позже его примеру последовали и основные браузеры, которые также предоставили этот интерфейс. Позднее W3C стандартизировал его и предложилXMLHttpRequest
стандартный.XMLHttpRequest
Стандарт делится наLevel 1
а такжеLevel 2
.XMLHttpRequest Level 1
Основные недостатки заключаются в следующем:
-
В соответствии с политикой одного и того же источника отправка междоменных запросов невозможна;
-
Невозможно отправлять двоичные файлы (такие как изображения, видео, аудио и т. д.), только текстовые данные;
-
В процессе отправки и получения данных информация о ходе работы не может быть получена в режиме реального времени, и можно судить только о том, завершен ли он;
ТакLevel 2
правильноLevel 1
улучшен,XMLHttpRequest Level 2
Были добавлены следующие функции:
-
Можно отправлять междоменные запросы, если это позволяет сервер;
-
Поддержка отправки и получения двоичных данных;
-
Добавлен объект formData для поддержки отправки данных формы;
-
При отправке и получении данных можно получить информацию о ходе выполнения;
-
Период ожидания запроса может быть установлен;
Конечно, для более подробного сравнения вы можете обратиться кЭта статья г-на Руана, в статье есть конкретные примеры кода для новых функций.
XMLHttpRequest
совместимость
оxhr
совместимость с браузером, вы можете напрямую просматривать результаты, предоставленные веб-сайтом «Могу ли я использовать»Совместимость XMLHttpRequest, скриншот приведен ниже.
Как видно из рисунка:
-
IE8/IE9, Opera Mini вообще не поддерживаются
xhr
объект -
IE10/IE11 частично поддерживается, не поддерживается
xhr.responseType
дляjson
-
Некоторые браузеры не поддерживают настройку таймаута запроса, то есть его нельзя использовать
xhr.timeout
-
Некоторые браузеры не поддерживают
xhr.responseType
дляblob
разрабатыватьXMLHttpRequest
как использовать
Давайте сначала посмотрим на использованиеXMLHttpRequest
ОтправитьAjax
Простой пример кода для запроса.
function sendAjax() {
//构造表单数据
var formData = new FormData();
formData.append('username', 'johndoe');
formData.append('id', 123456);
//创建xhr对象
var xhr = new XMLHttpRequest();
//设置xhr请求的超时时间
xhr.timeout = 3000;
//设置响应返回的数据格式
xhr.responseType = "text";
//创建一个 post 请求,采用异步
xhr.open('POST', '/server', true);
//注册相关事件回调处理函数
xhr.onload = function(e) {
if(this.status == 200||this.status == 304){
alert(this.responseText);
}
};
xhr.ontimeout = function(e) { ... };
xhr.onerror = function(e) { ... };
xhr.upload.onprogress = function(e) { ... };
//发送数据
xhr.send(formData);
}
Вышеупомянутое является использованиемxhr
В качестве примера отправки данных формы вы можете обратиться к комментариям для всего процесса.
Далее я буду стоять на точке зрения пользователя и представлю ее в форме вопроса.
xhr
базовое использование.
Я подробно расскажу о знаниях, связанных с каждым вопросом, и некоторые знания могут быть вами упущены.
Как установить заголовок запроса
отправкаAjax
просьба (по существуHTTPrequest), нам может понадобиться установить некоторую информацию заголовка запроса, такую какcontent-type
,connection
,cookie
,accept-xxx
Ждать.xhr
при условииsetRequestHeader
чтобы мы могли изменить запрос
заголовок.
void setRequestHeader(DOMString header, DOMString value);
будь осторожен:
-
Заголовок первого параметра метода нечувствителен к регистру, то есть его можно записать в виде
content-type
, что также можно записать какContent-Type
, или даже пишется какcontent-Type
; -
Content-Type
Значение по умолчанию связано с конкретным типом отправляемых данных, см. раздел [Какие типы данных можно отправлять] этой статьи; -
setRequestHeader
Должен бытьopen()
После метода,send()
Метод вызывается раньше, иначе будет выброшена ошибка; -
setRequestHeader
Может вызываться несколько раз, конечное значение не будет перезаписаноoverride
способ, но добавлениеappend
Путь. Вот пример кода:
var client = new XMLHttpRequest();
client.open('GET', 'demo.cgi');
client.setRequestHeader('X-Test', 'one');
client.setRequestHeader('X-Test', 'two');
// 最终request header中"X-Test"为: one, two
client.send();
Как получить заголовок ответа
xhr
Для получения заголовков ответов предусмотрено два метода:getAllResponseHeaders
а такжеgetResponseHeader
. Первый — получить все поля заголовка в ответе, а второй — получить значение указанного поля заголовка. Кроме того,getResponseHeader(header)
изheader
Аргументы не чувствительны к регистру.
DOMString getAllResponseHeaders();
DOMString getResponseHeader(DOMString header);
Эти два метода кажутся простыми, но везде есть подводные камни.
Вы сталкивались с ямой внизу? - Во всяком случае, сталкивались. . .
-
использовать
getAllResponseHeaders()
увидеть всеresponse header
с настоящей консольюNetwork
видел вresponse header
Разные -
использовать
getResponseHeader()
получитьheader
значение, браузер выдает ошибкуRefused to get unsafe header "XXX"
После некоторых поисков, наконецStack Overflow нашел ответ.
-
Причина 1:Ограничения сделаны в стандарте W3C xhr., который указывает, что клиент не может получить ответ в
Set-Cookie
,Set-Cookie2
Эти два поля, будь то однодоменный или междоменный запрос; -
Причина 2:Стандарт W3C cors также ограничивает междоменные запросы., который предусматривает, что для междоменных запросов поле заголовка ответа, которое может получить клиент, ограничено "
simple response header
"а также"Access-Control-Expose-Headers
(объяснение обоих терминов см. ниже).
"
simple response header
"Включенные поля заголовка:Cache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
,Pragma
;
"Access-Control-Expose-Headers
": Первое, на что следует обратить внимание, это"Access-Control-Expose-Headers
"провестимеждоменный запросЭто поле в заголовке ответа, для запроса того же домена в заголовке ответа нет этого поля. указан в этом поле Поле заголовка — это поле, которое сервер разрешает показывать клиенту.
такgetAllResponseHeaders()
получить толькоза пределы(то есть рассматривается какsafe
) поля заголовка, а не всех полей; вместо этого вызовgetResponseHeader(header)
метод,header
параметр должен бытьза пределыполе заголовка, иначе вызов сообщитRefused to get unsafe header
ошибка.
Как указатьxhr.response
тип данных
Иногда мы желаемxhr.response
Возвращается тип данных, который нам нужен. Например: данные, возвращаемые в ответе, представляют собой простую строку JSON, но мы ожидаем, чтоxhr.response
То, что мы получаем, это объект js напрямую, как мы его реализуем?
Есть 2 способа добиться этого, один из нихlevel 1
при условииoverrideMimeType()
метод, другойlevel 2
только при условииxhr.responseType
Атрибуты.
xhr.overrideMimeType()
overrideMimeType
даxhr level 1
Метод есть, так что совместимость браузера хорошая. Цель этого метода состоит в том, чтобы переопределитьresponse
изcontent-type
, какой смысл это делать? Например: сервер возвращает копию клиентуdocument
илиxml
документации, мы надеемся в конечном итоге пройтиxhr.response
есть одинDOM
объект, то вы можете использоватьxhr.overrideMimeType('text/xml; charset = utf-8')
реализовать.
Чтобы дать другой сценарий использования, мы все знаемxhr level 1
Прямая передача двоичных данных большого двоичного объекта не поддерживается, так что, если вы действительно хотите передать большой двоичный объект? использовалoverrideMimeType
метод решения этой проблемы.
Вот пример кода для получения файла изображения:
var xhr = new XMLHttpRequest();
//向 server 端获取一张图片
xhr.open('GET', '/path/to/image.png', true);
// 这行是关键!
//将响应数据按照纯文本格式来解析,字符集替换为用户自己定义的字符集
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.onreadystatechange = function(e) {
if (this.readyState == 4 && this.status == 200) {
//通过 responseText 来获取图片文件对应的二进制字符串
var binStr = this.responseText;
//然后自己再想方法将逐个字节还原为二进制数据
for (var i = 0, len = binStr.length; i < len; ++i) {
var c = binStr.charCodeAt(i);
//String.fromCharCode(c & 0xff);
var byte = c & 0xff;
}
}
};
xhr.send();
в примере кодаxhr
Запрос на изображение, добавивresponse
изcontent-type
Измените на «text/plain; charset=x-user-defined», чтобыxhr
Проанализируйте полученные данные большого двоичного объекта в текстовом формате, конечный пользовательthis.responseText
GOT - это двоичная строка, соответствующая файлу изображения, и, наконец, преобразует его в данные BLOB.
xhr.responseType
responseType
даxhr level 2
Новый атрибут, указывающийxhr.response
Тип данных, все еще есть некоторые проблемы с совместимостью, вы можете обратиться к [XMLHttpRequest
Совместимость] в этом разделе. ТакresponseType
Какие форматы можно задать?Я просто сделал таблицу следующим образом:
стоимость | xhr.response тип данных |
иллюстрировать |
---|---|---|
"" |
String нить |
Значение по умолчанию (без установкиresponseType Время) |
"text" |
String нить |
|
"document" |
Document объект |
надеюсь вернутьсяXML используется при форматировании данных |
"json" |
javascript объект |
Проблема совместимости, IE10/IE11 не поддерживает |
"blob" |
Blob объект |
|
"arrayBuffer" |
ArrayBuffer объект |
Ниже приведен пример кода, который также получает изображение по сравнению сxhr.overrideMimeType
,использоватьxhr.response
добиться гораздо проще.
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
//可以将`xhr.responseType`设置为`"blob"`也可以设置为`" arrayBuffer"`
//xhr.responseType = 'arrayBuffer';
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
var blob = this.response;
...
}
};
xhr.send();
резюме
Хотя вxhr level 2
, они сосуществуют. Но найти не сложно,xhr.responseType
это заменитьxhr.overrideMimeType()
из,xhr.responseType
намного мощнее,xhr.overrideMimeType()
сможет сделатьxhr.responseType
может сделать это. Таким образом, теперь мы можем полностью отказаться от использованияxhr.overrideMimeType()
.
Как получить данные ответа
xhr
xhr.response
,xhr.responseText
,xhr.responseXML
-
xhr.response
-
По умолчанию: пустая строка
""
-
Это свойство имеет правильное значение после завершения запроса.
-
Если запрос не завершен, значение этого свойства может быть
""
илиnull
, конкретно сxhr.responseType
Связанный: КогдаresponseType
для""
или"text"
, значение""
;responseType
Для других значений значение равноnull
-
-
xhr.responseText
-
По умолчанию пустая строка
""
-
только тогда, когда
responseType
для"text"
,""
час,xhr
Это свойство доступно только для объекта и может быть вызвано только в данный момент.xhr.responseText
, иначе выдать ошибку -
Правильное значение можно получить только при успешном выполнении запроса. В следующих двух случаях значение представляет собой пустую строку.
""
: запрос не выполнен, запрос не выполнен
-
-
xhr.responseXML
-
По умолчанию
null
-
только тогда, когда
responseType
для"text"
,""
,"document"
час,xhr
Это свойство доступно только для объекта и может быть вызвано только в данный момент.xhr.responseXML
, иначе выдать ошибку -
Правильное значение может быть получено только тогда, когда запрос выполнен успешно и возвращаемые данные верны. Следующие три случая являются значениями
null
: когда запрос не выполнен, запрос завершается с ошибкой, запрос выполняется успешно, но возвращаемые данные не могут быть правильно проанализированы.
-
как отслеживатьajax
текущее состояние заявки
размещение одногоajax
После запроса, что, если вы хотите отследить, в каком состоянии сейчас находится запрос?
использоватьxhr.readyState
Это свойство можно проследить. Это свойство доступно только для чтения с 5 возможными значениями, соответствующимиxhr
разные этапы. каждый разxhr.readyState
При изменении значения срабатываетxhr.onreadystatechange
События, мы можем сделать соответствующие государственные суждения в этом событии.
xhr.onreadystatechange = function () {
switch(xhr.readyState){
case 1://OPENED
//do something
break;
case 2://HEADERS_RECEIVED
//do something
break;
case 3://LOADING
//do something
break;
case 4://DONE
//do something
break;
}
стоимость | условие | описывать |
---|---|---|
0 |
UNSENT (исходное состояние, не открыто) |
В настоящее времяxhr объект успешно построен,open() метод не вызывался |
1 |
OPENED (открыто, не отправлено) |
open() метод был вызван успешно,send() Метод еще не вызывался. Примечание: толькоxhr вOPENED государство, чтобы позвонитьxhr.setRequestHeader() а такжеxhr.send() , иначе будет сообщено об ошибке |
2 |
HEADERS_RECEIVED (полученные заголовки ответов) |
send() Метод был вызван, заголовки ответа и статус ответа были возвращены |
3 |
LOADING (Скачивание тела ответа) |
тело ответа (response entity body ) скачивается, в этом состоянии проходитxhr.response возможно, уже есть данные ответа |
4 |
DONE (Весь процесс передачи данных заканчивается) |
Весь процесс передачи данных завершается, независимо от того, был ли запрос выполнен успешно или нет. |
Как установить время ожидания запроса
Если запрос долгое время не был успешным, чтобы не занимать ресурсы сети попусту, мы вообще будем активно завершать запрос.XMLHttpRequest
при условииtimeout
свойство, позволяющее установить тайм-аут для запроса.
xhr.timeout
Единица: миллисекунды миллисекунды
По умолчанию:0
, т.е. не устанавливать тайм-аут
Многие студенты знают, что:запрос на запусксчитать, если большеtimeout
Если запрос времени не завершен (включая успех/неудачу), событие ontimeout будет инициировано для активного завершения запроса.
[Так когда же это будетзапрос на запуск? 】
——xhr.onloadstart
Когда событие срабатывает, то есть вы вызываетеxhr.send()
время метода.
потому чтоxhr.open()
просто создает соединение, но фактически не запускает передачу данных, иxhr.send()
Здесь начинается настоящий процесс передачи данных. только звониxhr.send()
, вызоветxhr.onloadstart
.
[Так когда же это будетконец запроса? 】
——xhr.loadend
когда событие срабатывает.
Кроме того, есть две ямы, которые требуют внимания:
-
допустимый
send()
установить это позжеxhr.timeout
, но начальной точкой синхронизации по-прежнему является вызовxhr.send()
момент метода. -
когда
xhr
для одногоsync
При синхронном запросеxhr.timeout
должен быть установлен на0
, иначе будет выброшена ошибка. По этой причине см. раздел [Как отправить синхронный запрос] этой статьи.
Как отправить синхронный запрос
xhr
По умолчанию отправляются асинхронные запросы, но синхронные запросы также поддерживаются (конечно, этого следует избегать в реальной разработке). Является ли это асинхронным или синхронным запросом, определяетсяxhr.open()
входящийasync
решение по параметрам.
open(method, url [, async = true [, username = null [, password = null]]])
-
method
: метод запроса, напримерGET/POST/HEADER
д., этот параметр не чувствителен к регистру -
url
: запрошенный адрес, который может быть относительным адресом, напримерexample.php
,этоотносительноотносительно текущей страницыurl
путь; также может быть абсолютным адресом, напримерhttp://www.example.com/example.php
-
async
: значение по умолчаниюtrue
, который является асинхронным запросом, еслиasync=false
, это синхронный запрос
До того, как я серьёзно изучил стандарт xhr W3C, я всегда думал, что синхронный запрос и асинхронный запрос — это только разница между блокирующим и неблокирующим, а остальные триггеры событий и настройки параметров должны быть одинаковыми, оказывается, я ошибался.
Стандарт W3C xhr оopen()
Метод имеет следующее описание:
Throws an "InvalidAccessError" exception if async is false, the JavaScript global environment is a document environment, and either the timeout attribute is not zero, the withCredentials attribute is true, or the responseType attribute is not the empty string.
Из предыдущего абзаца видно, что когдаxhr
Для синхронных запросов применяются следующие ограничения:
-
xhr.timeout
должно быть0
-
xhr.withCredentials
должно бытьfalse
-
xhr.responseType
должно быть""
(Обратите внимание"text"
тоже нельзя)
Если какое-либо из вышеперечисленных ограничений не выполняется, будет выдано сообщение об ошибке, а для асинхронных запросов ограничений на настройку этих параметров нет.
Я уже говорил, что страница должна стараться избегать использованияsync
Синхронный запрос, почему?
Потому что мы не можем установить время ожидания запроса (xhr.timeout
для0
, то есть неограниченное время). Без ограничения тайм-аута возможно, что синхронный запрос был вpending
состояние, сервер не возвращает ответ, поэтому вся страница будет постоянно заблокирована, не в состоянии реагировать на другие действия пользователя.
Кроме того, в стандарте не упоминается ограничение запуска событий во время синхронных запросов, но в реальной разработке я столкнулся с некоторыми событиями, которые должны запускаться, но не запускаться. Как в хроме, когдаxhr
для синхронного запроса, вxhr.readyState
Зависит от2
стали3
, не заводитсяonreadystatechange
мероприятие,xhr.upload.onprogress
а такжеxhr.onprogress
Событие также не срабатывает.
Как получить ход загрузки и загрузки
При загрузке или загрузке относительно больших файлов общим требованием к продукту является отображение текущей загрузки и загрузки в режиме реального времени.
мы можем пройтиonprogress
Событие для отображения прогресса в реальном времени, по умолчанию это событие срабатывает каждые 50 мс. Следует отметить, что процесс загрузки и процесс загрузки запускают разные объекты.onprogress
мероприятие:
-
Загрузка инициируется
xhr.upload
объектonprogress
мероприятие -
Загрузка инициируется
xhr
объектonprogress
мероприятие
xhr.onprogress = updateProgress;
xhr.upload.onprogress = updateProgress;
function updateProgress(event) {
if (event.lengthComputable) {
var completedPercent = event.loaded / event.total;
}
}
какой тип данных может быть отправлен
void send(data);
xhr.send(data)
Данные параметров могут быть следующих типов:
-
ArrayBuffer
-
Blob
-
Document
-
DOMString
-
FormData
-
null
Если это запрос GET/HEAD,send()
Методы обычно не передают параметры или передаютnull
. Но даже если вы передаете параметры, они в конечном итоге игнорируются,xhr.send(data)
Данные будут установлены наnull
.
xhr.send(data)
Тип данных параметра данных повлияет на заголовок запроса.content-type
Значение по умолчанию:
-
если
data
даDocument
типа, такжеHTML Document
введите, затемcontent-type
По умолчаниюtext/html;charset=UTF-8
; иначеapplication/xml;charset=UTF-8
; -
если
data
даDOMString
Типы,content-type
По умолчаниюtext/plain;charset=UTF-8
; -
если
data
даFormData
Типы,content-type
По умолчаниюmultipart/form-data; boundary=[xxx]
-
если
data
это другой тип, он не будет установленcontent-type
значение по умолчанию
Конечно это простоcontent-type
значение по умолчанию, но если вы используетеxhr.setRequestHeader()
установить вручнуюcontent-type
значение, указанное выше значение по умолчанию будет переопределено.
Кроме того, следует отметить, что если вызов осуществляется в отключенном состоянииxhr.send(data)
метод, он выдаст ошибку:Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest'
. Как только программа выдает ошибку, она не может продолжать выполнять следующий код без перехвата, поэтому вызовитеxhr.send(data)
метод, вы должны использоватьtry-catch
Отловить ошибки.
try{
xhr.send(data)
}catch(e) {
//doSomething...
};
xhr.withCredentials
а такжеCORS
какие отношения
Все мы знаем, что при отправке одного и того же доменного запроса браузер
cookie
автоматически добавляется вrequest header
середина. А вы когда-нибудь сталкивались с таким сценарием: при отправке междоменного запроса,cookie
не добавляется автоматически вrequest header
середина.
Причина этой проблемы:CORS
В стандарте оговорено, что по умолчанию браузеры не могут отправлять никакую аутентификационную информацию при отправке междоменных запросов (credentials
)Такие как"cookies
"а также"HTTP authentication schemes
".пока неxhr.withCredentials
дляtrue
(xhr
Объект имеет свойство, называемоеwithCredentials
, значение по умолчаниюfalse
).
Итак, первопричиной являетсяcookies
Это также своего рода аутентификационная информация.client
необходимо установить вручнуюxhr.withCredentials=true
,а такжеserver
конец также должен позволятьrequest
Может нести аутентификационную информацию (т.response header
содержитAccess-Control-Allow-Credentials:true
), чтобы браузер автоматическиcookie
Добавить вrequest header
середина.
Кроме того, обратите особое внимание на один момент, когда-то междоменныйrequest
может нести аутентификационную информацию,server
Конец не должен бытьAccess-Control-Allow-Origin
Установить как*
, но должно быть установлено на доменное имя запрашивающей страницы.
xhr
Связанные события
классификация событий
xhr
Событий так много, что иногда трудно вспомнить. Но когда я понимаю конкретную реализацию кода, это легко понять. НижеXMLHttpRequest
Часть кода реализации:
interface XMLHttpRequestEventTarget : EventTarget {
// event handlers
attribute EventHandler onloadstart;
attribute EventHandler onprogress;
attribute EventHandler onabort;
attribute EventHandler onerror;
attribute EventHandler onload;
attribute EventHandler ontimeout;
attribute EventHandler onloadend;
};
interface XMLHttpRequestUpload : XMLHttpRequestEventTarget {
};
interface XMLHttpRequest : XMLHttpRequestEventTarget {
// event handler
attribute EventHandler onreadystatechange;
readonly attribute XMLHttpRequestUpload upload;
};
Из кода мы видим, что:
-
XMLHttpRequestEventTarget
Интерфейс определяет 7 событий:-
onloadstart
-
onprogress
-
onabort
-
ontimeout
-
onerror
-
onload
-
onloadend
-
-
Каждый
XMLHttpRequest
Eстьupload
свойства, при этомupload
ЯвляетсяXMLHttpRequestUpload
объект -
XMLHttpRequest
а такжеXMLHttpRequestUpload
унаследовал то же самоеXMLHttpRequestEventTarget
интерфейс, такxhr
а такжеxhr.upload
В первой статье перечислены 7 событий. -
onreadystatechange
даXMLHttpRequest
уникальное событие
Итак, с первого взгляда все ясно:xhr
Всего 8 связанных событий: 7XMLHttpRequestEventTarget
Событие +1 уникальноеonreadystatechange
событие; иxhr.upload
только 7XMLHttpRequestEventTarget
мероприятие.
триггер события
Ниже тот, который я сделал самxhr
Таблица условий срабатывания связанных событий, наиболее примечательной из которых являетсяonerror
Условие запуска события.
мероприятие | Условия срабатывания |
---|---|
onreadystatechange |
в любое времяxhr.readyState Срабатывает при изменении; ноxhr.readyState Фей0 значение становится0 не срабатывает. |
onloadstart |
передачаxhr.send() Запускается сразу после метода, еслиxhr.send() Если не вызывается, это событие не будет запущено. |
onprogress |
xhr.upload.onprogress На этапе загрузки (т.xhr.send() Позже,xhr.readystate=2 до) триггер, триггер каждые 50 мс;xhr.onprogress На этапе загрузки (т.xhr.readystate=3 time) срабатывает раз в 50 мс. |
onload |
Запускается при успешном выполнении запроса, в это времяxhr.readystate=4 |
onloadend |
Запускается, когда запрос завершается (включая успех запроса и отказ запроса) |
onabort |
при звонкеxhr.abort() пост-триггер |
ontimeout |
xhr.timeout Не равно 0, начиная с запросаonloadstart начать считать, когда прибудетxhr.timeout Запрос установленного времени еще не завершенonloadend , это событие срабатывает. |
onerror |
Во время запроса, еслиNetwork error вызовет это событие (еслиNetwork error , загрузка еще не завершена, она сработает первойxhr.upload.onerror , запустить сноваxhr.onerror ; если это произойдетNetwork error , загрузка завершена, она сработает толькоxhr.onerror ).Уведомление, это событие будет инициировано только при возникновении исключения на уровне сети. Для исключений на уровне приложения, таких как возвращенный ответxhr.statusCode да4xx , не принадлежитNetwork error , так что не сработаетonerror событие, но вызоветonload мероприятие. |
Последовательность запуска события
Когда с запросом все в порядке, соответствующая последовательность срабатывания события выглядит следующим образом:
-
вызывать
xhr.onreadystatechange
(каждый раз послеreadyState
Когда он изменится, он сработает один раз) -
вызывать
xhr.onloadstart
//Начало фазы загрузки: -
вызывать
xhr.upload.onloadstart
-
вызывать
xhr.upload.onprogress
-
вызывать
xhr.upload.onload
-
вызывать
xhr.upload.onloadend
//Загрузка завершена, и начинается фаза загрузки: -
вызывать
xhr.onprogress
-
вызывать
xhr.onload
-
вызывать
xhr.onloadend
происходитьabort
/timeout
/error
Обработка исключений
В процессе запроса может произойтиabort
/timeout
/error
эти 3 исключения. Затем, когда эти исключения происходят,xhr
Что будет сделано дальше? Дальнейшая обработка выглядит следующим образом:
-
как только это произойдет
abort
илиtimeout
илиerror
Исключение, немедленно прервать текущий запрос -
Буду
readystate
установлен в4
, и триггерыxhr.onreadystatechange
мероприятие -
Если фаза загрузки не завершена, последовательно запускаются следующие события:
-
xhr.upload.onprogress
-
xhr.upload.[onabort或ontimeout或onerror]
-
xhr.upload.onloadend
-
-
вызывать
xhr.onprogress
мероприятие -
вызывать
xhr.[onabort或ontimeout或onerror]
мероприятие -
вызывать
xhr.onloadend
мероприятие
в которомxhr
Обратный вызов успешно зарегистрирован в событии?
Из событий, описанных выше, можно узнать, что еслиxhr
Если запрос выполнен успешно, он сработаетxhr.onreadystatechange
а такжеxhr.onload
два события. Итак, в каком событии мы регистрируем обратный вызов успеха? я склоняюсь кxhr.onload
событие, потому чтоxhr.onreadystatechange
каждый разxhr.readyState
будет срабатывать при изменении вместоxhr.readyState=4
срабатывает когда.
xhr.onload = function () {
//如果请求成功
if(xhr.status == 200){
//do successCallback
}
}
Приведенный выше пример кода является очень распространенным способом написания: сначала оценитеhttp
Является ли код состояния200
, если это так, запрос считается успешным, и выполняется обратный вызов успеха. В таких суждениях есть подводные камни, например, при возвращенииhttp
код состояния не200
, но201
, запрос также выполнен успешно, но логика обратного вызова не выполняется. Следовательно, более надежным методом суждения должен быть: когдаhttp
Код состояния2xx
или304
считается успешным.
xhr.onload = function () {
//如果请求成功
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
//do successCallback
}
}
Эпилог
Наконец-то закончил писать...
После прочтения этого длинного стандарта W3C xhr у меня глаза заплыли...
Надеюсь, это краткое изложение поможет тем, кто только начинаетXMLHttpRequest
ты.
Наконец, дайте несколько расширенных учебных материалов, если вы:
-
хочу действительно понять
XMLHttpRequest
, самый надежный способ - посмотреть наСтандарт W3C xhr; -
Хотите научиться использовать код
XMLHttpRequest
Отправить различные типы данных, вы можете обратиться кЭта статья на html5rocks -
хочу иметь приблизительное представление
XMLHttpRequest
Основное использование , вы можете обратиться кВведение в XMLHttpRequest MDN; -
хочу знать
XMLHttpRequest
процесс разработки, вы можете обратиться кСтатья учителя Руана; -
хочу знать
Ajax
Для основного введения вы можете обратиться кAJAX Tutorial; -
Если вы хотите узнать о междоменных запросах, вы можете обратиться кКорс-стандарт W3C;
-
хочу знать
http
соглашение, вы можете обратиться кHTTP Tutorial;