Как мы знаем из предыдущей статьи, AJAX — это общий термин для ряда технологий. В этой статье мы пойдем еще дальше и подробно объясним, как использовать технологию Ajax для извлечения данных в проекте. И для того, чтобы объяснить это ясно, мы должны сначала выяснить, что мыгде взять данныеДа, второе, на что мы обращаем внимание, этоКак получить данные.
1. Получение данных
Мы знаем, что AJAX используется в проектах для извлечения данных таким образом, чтобы предотвратить обновление страницы, так откуда берутся данные? Откуда мы знаем, как получить эти данные? Ответ заключается в том, что мы обычно используемAPIВзаимодействуйте с различными базами данных.
«API» — это сокращение от «интерфейс прикладного программирования», вы можете себе представить, что некоторые данные открыты и ожидают использования, и мы получаем эти данные с помощью API. API обычно имеет форму URL-адреса и предоставляет указанное имя параметра и значение параметра, чтобы помочь вам найти данные, которые вы хотите получить.
Помните, мы упоминали, что AJAX требует соответствующей настройки на стороне сервера? Мы вернемся к этому позже.
Во-вторых, ядро технологии AJAX — объект XMLHttpRequest.
Давайте отложим настройку на стороне сервера и сосредоточимся на основных аспектах технологии AJAX:XMLHttpRequest
объект.
XMLHttpRequest
Объект представляет собой API, предоставляемый браузером для беспрепятственной отправки запросов на сервер и анализа ответа сервера.Конечно, страница браузера не будет обновляться в течение всего процесса. Это будет главный герой оставшейся части этой статьи, давайте сначала встанем на высокий уровень и получим общий обзор объекта:
-
XMLHttpRequest
Просто объект JavaScript, точнее,Конструктор. Другими словами, это вовсе не загадочно, оно особенное только тем, что предоставляется клиентом (т.new
Ключевые слова созданы, нам просто нужно их освоить; -
XMLHttpRequest
Объекты постоянно расширяются. С широким распространением объектов XML W3C также начал разрабатывать соответствующие стандарты для регулирования их поведения. В настоящее время,XMLHttpRequest
Существует два уровня: уровень 1 предоставляет детали реализации объекта XML, а уровень 2 обеспечивает дальнейшую разработку объекта XML, добавляя некоторые дополнительные методы, свойства и типы данных. Однако не все браузеры реализуют содержимое XML-объекта уровня 2 (не неожиданно, правда?);
Начнем с разборкиXMLHttpRequest
Свойства и методы экземпляра Для начала создайте экземпляр объекта XML:
const xhr = new XMLHttpRequest()
Свойства экземпляра, методы:
метод
-
.open()
: готов к запуску AJAX-запроса; -
.setRequestHeader()
: установить информацию заголовка запроса; -
.send()
: отправить запрос AJAX; -
.getResponseHeader()
: получить информацию заголовка ответа; -
.getAllResponseHeader()
: получить длинную строку, содержащую всю информацию заголовка; -
.abort()
: отменить асинхронный запрос;
Атрибуты
-
.responseText
: содержит возвращаемый текст тела ответа; -
.responseXML
: если тип содержимого ответаtext/xml
илиapplication/xml
, который будет содержать документ XML DOM, содержащий соответствующие данные; -
.status
: HTTP-статус ответа; -
.statusText
: Описание статуса HTTP; -
.readyState
: Указывает текущую активную стадию процесса «запрос»/«ответ».
Кроме того, браузер предоставляетonreadystatechange
Прислушивайтесь к событиям всякий раз, когда экземпляр XMLreadyState
Это событие запускается при изменении свойства.
На данный момент перечислены все методы атрибутов объекта экземпляра XMLHttpRequest. Далее мы подробнее рассмотрим, как использовать эти методы и атрибуты для завершения процесса отправки запросов AJAX.
3. Подготовьте AJAX-запросы
Для взаимодействия с сервером нам сначала нужно ответить на следующие вопросы:
- Мы собираемся извлекать данные или хранить данные? -- Проявляется как разница в методе запроса:
GET
илиPOST
; - Куда сделать запрос? --Соответствующий адрес API;
- Каким образом ждать ответа? --имеют"Синхронизировать"а также"асинхронный"Два варианта; (Передача по сети - это процесс, запрос и ответ не происходят одновременно.)
Экземпляр XMLHttpRequest.open()
Роль метода состоит в том, чтобы ответить на три вышеуказанных вопроса..open()
Метод принимает три параметра:метод запроса,URL-адрес запросаа такжелогическое значение для асинхронного запроса.
Ниже приведен.open()
Пример вызова метода:
// 该段代码会启动一个针对“example.php”的GET同步请求。
xhr.open("get", "example.php", false)
Это равносильно подготовке инструментов и мытью посуды перед тем, как начать готовить..open()
Этот метод также хорошо справляется с подготовкой к отправке AJAX-запроса.
Теперь давайте углубимся в некоторые детали подготовки:
(1) Получить запрос и почтовый запрос
- ПОЛУЧИТЬ запрос
GET-запросы используются дляполучить данные, иногда данные, которые нам нужно получить, должны быть расположены через «параметры запроса», в этом случае мы добавим параметры запроса в конец URL-адреса, чтобы сервер выполнил синтаксический анализ.
Параметр запроса — это?
номер, начинающийся с&
Строка, разделенная символами, содержащая соответствующие пары ключ-значение. Используется, чтобы сообщить браузеру, какой конкретный ресурс запрашивать.
const query = "example.php?name=tom&age=24" // "?name=tom&age=24"即是一个查询参数
Следует отметить, что имя и значение каждого параметра в строке запроса должны быть закодированы с помощью encodeURIComponent() (это связано с тем, что некоторые символы в URL-адресе могут вызвать неоднозначность, например "&").
- POST-запрос
POST-запросы используются дляОтправить данные на сервер, которые должны быть сохранены, поэтому запрос POST, естественно, требует на одну копию больше, чем запрос GET.данные для сохранения. Итак, где должны быть размещены эти данные? Ведь наш.open()
Ни один из трех параметров, которые получает метод, не имеет подходящего местоположения.
Ответ заключается в том, что данные, которые необходимо отправить, будут.send()
Наконец, параметры метода отправляются на сервер, а данные могут быть любого размера и любого типа.
Вот две вещи, на которые следует обратить внимание:
-
.send()
Параметры метода не обнуляемы, то есть для GET-запросов, которым не нужно отправлять никаких данных, их тоже нужно вызывать.send()
метод, пройтиnull
стоимость; - Пока что нам известно два способа отправки данных на сервер:отправка формытак же какотправить POST-запрос, следует отметить, что сервер не обрабатывает эти два метода одинаково, а это означает, что сервер должен иметь соответствующий код для обработки необработанных данных, отправленных запросом POST.
Но, к счастью, мы можем смоделировать отправку формы через POST-запрос, всего в два простых шага:
- Задайте параметры заголовка запроса:
Content-Type: application/x-www-form-urlencoded
(тип содержимого при отправке формы); - Сериализировать данные формы в форму строки запроса, передать
.send()
метод;
(2) URL запроса
Здесь следует отметить, что если используется относительный путь, URL-адрес запросаотносительно текущей страницы, на которой выполняется код.
(3) Синхронный запрос и асинхронный запрос
Люди обычно думают, что AJAX является асинхронным, но на самом деле это не так. AJAX — это технология, позволяющая избежать обновления страницы после выборки данных.Что касается того, ждать ли ответа сервера синхронно или асинхронно, разработчики должны настроить его в соответствии с требованиями бизнеса. (хотя обычно асинхронный).
Вам может быть интересно, когда нам нужно использовать синхронный AJAX? Из моего личного опыта кажется, что найти соответствующую сцену сложно. Аналогичный вопрос есть на Stack Overflow, если интересно, нажмитеПроверить.
Наконец, давайте кратко объясним разницу между «синхронным» ожиданием ответа и «асинхронным» ожиданием ответа: «синхронный» означает, что после отправки запроса любой последующий код JavaScript не будет выполняться, а «асинхронный» означает, что после отправки запроса последующий код JavaScript будет продолжать выполняться, и когда запрос будет успешным, будет вызвана соответствующая функция обратного вызова.
В-четвертых, установите заголовок запроса
Каждый HTTP-запрос и ответ будут иметь соответствующую информацию заголовка, включая некоторую информацию, связанную с данными, сетевым окружением и статусом отправителя и т. д. предоставляется объектом XMLHttpRequest.setRequestHeader()
Этот метод предоставляет разработчикам возможность манипулировать этими двумя данными заголовка и позволяет разработчикам настраивать информацию заголовка заголовка запроса.
По умолчанию при отправке AJAX-запроса включаются следующие заголовки:
-
Accept
: тип контента, который может обрабатывать браузер; -
Accept-Charset
: набор символов, который может отображать браузер; -
Accept-Encoding
: кодировка сжатия, которую может обрабатывать браузер; -
Accept-Language
: язык, установленный браузером в данный момент; -
Connection
: тип соединения между браузером и сервером; -
Cookie
: любые файлы cookie, установленные текущей страницей; -
Host
: домен страницы, с которой был сделан запрос; -
Referer
: URI страницы, делающей запрос; -
User-Agent
: строка пользовательского агента браузера;
Уведомление, некоторые браузеры не позволяют использовать.setRequestHeader()
Этот метод переопределяет информацию заголовка запроса по умолчанию, поэтому пользовательская информация заголовка запроса является более безопасным методом:
// 自定义请求头
xhr.setRequestHeader("myHeader", "MyValue")
5. Отправьте запрос
На данный момент мы полностью готовы отправить запрос: используйте.open()
Метод определяет метод запроса, метод ожидания ответа и адрес запроса, и даже через.setRequestHeader()
После настройки заголовков ответов наступает самый волнующий момент: используйте.send()
метод, отправьте запрос AJAX!
// 发送AJAX请求!
const xhr = new XMLHttpRequest()
xhr.open("get", "example.php", false)
xhr.setRequestHeader("myHeader", "goodHeader")
xhr.send(null)
Ну, немного неловко быть простым, не так ли? Попробуйте другой POST-запрос:
// 发送AJAX请求!
const xhr = new XMLHttpRequest()
xhr.open("post", "example.php", false)
xhr.setRequestHeader("myHeader", "bestHeader")
xhr.send(some_data)
Эм... все еще чувствуешь, что чего-то не хватает? Успокойся, чувак, потому что мы только что сделали запрос, еще нет.обрабатывать ответ, давайте посмотрим на это.
6. Обработка ответа
Давайте перейдем непосредственно к тому, как обрабатывать синхронный ответ на запрос GET:
const xhr = new XMLHttpRequest()
xhr.open("get", "example.php", false)
xhr.setRequestHeader("myHeader", "goodHeader")
xhr.send(null)
// 由于是同步的AJAX请求,因此只有当服务器响应后才会继续执行下面的代码
// 因此xhr.status的值一定不为默认值
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText)
} else {
alert("Request was unsuccessful: " + xhr.status)
}
Приведенный выше код понять несложно, мы передаем упомянутый ранее xhr.status
свойство (в котором хранится HTTP-статус ответа, если вы забыли), чтобы определить, был ли запрос успешным, если это так, мы прочитаем xhr.responseText
Возвращаемое значение, хранящееся в свойстве. Однако когда наш запрос асинхронный, проблема немного усложняется.Поскольку это асинхронный запрос, вxhr.send(null)
После того, как оператор будет выполнен, движок JavaScript немедленно выполнит следующий оператор суждения, и в это время, поскольку у нас не было времени ответить, нам суждено получить значение xhr.status по умолчанию, поэтому мы никогда не сможем получить запрошенное ресурс.
Как решить эту проблему? Ответ заключается в добавлении к экземпляру XMLHTTPRequestonreadystatechange
Обработчики событий (конечно, вы также можете напрямую использовать спецификацию уровня DOM2.addEventListener()
метод, но обратите внимание, что IE8 не поддерживает этот метод).
экземпляр xhrreadystatechange
Событие будет слушать xhr.readyState
Вы можете думать об этом свойстве как о счетчике, который продолжает накапливаться по мере выполнения процесса AJAX.Его возможные значения следующие:
-
0: неинициализировано -- еще не вызвано
.open()
метод; -
1: start -- был вызван
.open()
метод, но не был вызван.send()
метод; -
2:send -- уже звонили
.send()
метод, но пока не получил ответа; - 3:Receive -- получены данные частичного ответа;
- 4:complete -- все данные ответа получены и могут быть использованы на стороне клиента;
С этим обработчиком времени, контролирующим процесс AJAX, остальное намного проще.Код для асинхронного запроса GET выглядит следующим образом:
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readystate == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText)
} else {
alert("Request was unsuccessful: " + xhr.status)
}
}
}
xhr.open("get", "example.php", true)
xhr.send(null)
Уведомление: для обеспечения кроссбраузерной совместимости необходимо вызвать.open()
В конце концов, имеет смысл указывать обработчики событий перед методами..open()
Выполнение метода также включено в область прослушивания обработчика событий, верно?
Семь, отмените асинхронный запрос
Иногда может потребоваться отменить асинхронный запрос до получения ответа, в этом случае необходимо вызвать.abort()
метод.
Этот метод не позволяет экземпляру объекта XHR запускать события и больше не разрешает доступ к каким-либо свойствам объекта, связанным с ответом. Без монитора мы больше не можем судить об ответе, не так ли?
Однако следует отметить, что после завершения запроса AJAX вам необходимо вручную отменить привязку экземпляра объекта XHR, чтобы освободить место в памяти.
🎉🎉 Поздравляем! Здесь вы изучили все основы AJAX, вы знаете, что такое AJAX, что значит существовать и как на самом деле инициировать запрос AJAX и получить ответ, вы уже гуру AJAX! поздравляю! чудесный! 🎉🎉
🤜 Круто, дорогой мастер AJAX, ты еще не ушел, тогда я научу тебя последней части читов AJAX, которые помогут тебе стать настоящим ниндзя AJAX, которого побеждает твоя настойчивость!
8. Читы: XMLHttpRequest Level 2
Помните, мы упоминали в начале, что W3C предложил спецификацию XMLHttpRequest Level 2? Хотя не все браузеры реализуют то, что указано в этой спецификации, некоторые из них реализованы всеми или большинством браузеров. Хотите быть ниндзя AJAX? Посмотрите вниз.
Совет: В этой части вы увидите много текста о совместимости браузеров, надеюсь, вам не скучно, ведь это практика ниндзя, верно?
(1) Тип данных формы
FormData — это новый тип данных (конструктор), предоставляемый нам XMLHttpRequest level 2. Помните, как раньше мы маскировали POST-запрос под отправку формы? FormData упрощает этот процесс, поскольку объект XHR распознает, что входящий тип данных является экземпляром FormData, и автоматически настраивает соответствующие заголовки.
FormData используется следующим образом:
// 添加数据
let data1 = new FormData()
data1.append("name", "Tom")
xhr.send(data1)
// 提取表单数据
let data2 = new FormData(document.forms[0])
xhr.send(data2)
Кроме того, еще одно преимущество formdata состоит в том, что по сравнению с традиционными запросами Ajax это позволяет загружать двоичные данные (изображения, видео, аудио и т. Д.). Для получения подробной информации см.Связь.
Браузерная совместимость FormData:
- рабочий стол
- IE 10+ и другие браузеры поддерживаются
- мобильный
- Поддерживаются Android, Firefox Mobile, OperaMobile, другие браузеры неизвестны
(2) Настройка времени ожидания
Когда мы отправляем AJAX-запрос и получаем ответ от сервера, это плохо. Чтобы облегчить это неприятное чувство, спецификация XMLHttpRequest уровня 2 предоставляет нам дополнительное свойство и событие прослушивателя событий:
-
timeout
Атрибут: установите время ожидания в миллисекундах; -
timeout
Событие: инициируется, когда время отклика превышает свойство timeout объекта экземпляра;
Он используется следующим образом:
// 当响应时间超过1秒时,请求中止,弹出提示框
xhr.timeout = 1000
xhr.ontimeout = () => { alert("Request did not return in a second.") }
Обратите внимание, что когда запрос завершится, он будет вызванontimeout
обработчик событий, на этот раз xhrreadyState
Значение свойства могло измениться на 4, что означает продолжение вызова.onreadystatechange
обработчик событий, но когда тайм-аут прерывает запрос, а затем обращается к xhr'sstatus
свойство приведет к тому, что браузер выдаст ошибку, поэтому вам нужно проверитьstatus
оператор атрибута вtry-catch
в предложении.
Это немного хлопотно, но у нас больше контроля над объектом XMLHttpRequest.
Совместимость с браузером:
- рабочий стол
- IE 10+ и другие браузеры поддерживаются
- мобильный
- Поддерживаются IE Mobile 10+ и другие браузеры.
(3) метод overrideMimeType()
Заголовок ответа, возвращаемый ответом, описывает MIME-тип возвращаемых данных. Идентифицируя тип, браузер сообщает экземпляру XMLHttpRequest, как обрабатывать данные. Однако иногда (например, при обработке данных типа XML как обычного текста) мы хотим обрабатывать данные ответа так, как мы хотим, в спецификации XMLHttpRequest уровня 2 мы можем использовать.overrideMimeType()
Метод, как несложно догадаться из названия метода, может переопределять MIME-тип данных, описанных в заголовке ответа.
Это написано следующим образом:
const xhr = new XMLHttpRequest()
xhr.open("get", "example.php", true)
xhr.overrideMimeType("text/xml") // 强迫浏览器将响应数据以指定类型方式解读
xhr.send(null)
На этом этапе у нас есть контроль над тем, как обрабатываются данные ответа.
Совместимость с браузером:
- рабочий стол
- IE 7+ и другие браузеры поддерживаются
- мобильный
- Поддерживаются Firefox Mobile, Chrome для Android, другие браузеры неизвестны
(4) События прогресса
Спецификация событий прогресса была разработана рабочим проектом W3C. Спецификация определяет ряд событий, связанных с клиентом, и сервер связывается с этими различными прослушивателями события ключевым процессом узла, позволяет нам более эффективно управлять гранулярностью в деталях процесса передачи данных. В настоящее время существует шесть прогресс событий, они будут следовать за прогрессом передачи данных.
-
loadstart
: Запускается при получении первого байта данных ответа;- Рабочий стол: поддерживается всеми браузерами, кроме Safari Mobile.
- Мобильный: Поддерживается другими браузерами, кроме Safari. Мобильный неизвестен.
-
progress
: Запускается постоянно во время получения ответа;- Рабочий стол: поддерживаются IE10+ и другие браузеры.
- Мобильный: оба поддерживаются
-
error
: срабатывает при возникновении ошибки в запросе;- Рабочий стол: все браузеры поддерживают (Источники информации)
- Мобильный: все браузеры поддерживают его, кроме IE Mobile, который не поддерживается (Источники информации)
-
abort
: опять из-за звонкаabort()
метод запущен;- Рабочий стол: неизвестно
- Мобильный: неизвестно
-
load
: Запускается при получении полных данных ответа;- Рабочий стол: поддерживаются IE7+ и другие браузеры.
- Мобильные устройства: Chrome для Android, Edge, поддержка Firefox Mobile, другие браузеры неизвестны.
-
loadend
: После завершения или запуска связиerror
,abort
илиload
Запускается после события;- Рабочий стол: поддерживается не всеми браузерами.
- Мобильный: поддерживается не всеми браузерами.
Здесь мы сосредоточимся на следующих двух событиях:
① событие загрузки
Это событие помогло нам сохранитьreadstatechange
Событие, нам не нужно связать функцию слушателя событий на экземпляре объекта XHR для отслеживания экземпляраreadState
свойства меняются, но вы можете напрямую использовать следующий код:
const xhr = new XMLHttpRequest()
xhr.onload = () => {
if ((xhr.status >= 200 && xhr.status <300) || xhr.status == 304) {
alert(xhr.responseText)
} else {
alert("Something wrong!")
}
}
xhr.open("get", "example.php", true)
xhr.send(null)
② событие прогресса
Это событие позволяет нам достичь эффекта индикатора загрузки нашей мечты. потому чтоonprogress
Обработчик события получаетevent
объект, которыйtarget
Свойства являются экземплярами объекта XHR, но содержат три дополнительных свойства:
-
lengthComputable
: логическое значение, указывающее, доступна ли информация о ходе выполнения; -
position
: Указывает текущее количество полученных байтов; -
totalSize
: указывает ожидаемое количество байтов в соответствии с заголовком ответа Content-Length;
Очевидно, что все ресурсы, необходимые для нашего индикатора загрузки, готовы, нам просто нужно написать следующий код:
const xhr = new XMLHttpRequest()
xhr.onload = () => {
if ((xhr.status >= 200 && xhr.status <300) || xhr.status == 304) {
alert(xhr.responseText)
} else {
alert("Something wrong!")
}
}
// 加载进度条
xhr.onprogress = function(event) {
const divStatus = document.getElementById("status")
if (event.lengthComputable) {
divStatus.innerHTML = `Received ${event.postion} of ${event.totalSize} bytes`
}
}
xhr.open("get", "example.php", true)
xhr.send(null)
Все сделано! Но помниУведомление, должен быть в.open()
вызов перед методомonprogress
обработчик события.
Отлично, мне больше нечего сказать об AJAX, если вы освоили все вышеперечисленные концепции, то вы заслуживаете звания «AJAX Ninja».
Я действительно горжусь тобой, Великая Работа! 🙌
👋 Привет! Понравилась ли Вам эта статья? Не забудьте поставить лайк ниже👇 и дайте мне знать.