Javascript — синхронный ajax запрос (xmlhttprequest)
Содержание:
- Загрузка разметки на страницу с помощью метода load()
- Объект jqXHR
- 2 AJAX POST Example, the jQuery way
- Опции $.ajax
- Загрузка части страницы
- Настройка и фильтрация Ajax-запросов
- Ответ: status, statusText, responseText
- Преимущества технологии AJAX
- Description
- Как прочитать данные в формате JSON с помощью jQuery
- 4.1 Показать товары на странице при загрузке
- 4.2 Показать товары при клике на кнопку
- 4.3 Создание функции showProducts()
- 4.4 Получение списка товаров
- 4.5 Создание кнопки «Добавить товар»
- 4.6 Создание HTML-таблицы
- 4.7 Построение строки таблицы для каждой записи
- 4.8 Вставка контента на страницу
- 4.9 Изменение заголовка страницы
- Настройка базовых параметров Ajax-запросов
- Types
- Синхронные и асинхронные запросы
- Использование вспомогательных методов для работы с конкретными типами данных
- IE8,9: XDomainRequest
- Examples
Загрузка разметки на страницу с помощью метода load()
Очень удобный метод jQuery позволяет легко получать разметку HTML с сервера через AJAX и вставлять ее автоматически в текущую страницу. Если скрипт серверной стороны выполняет всю работу по обработке данных и формированию разметки, и вы хотите только вывести результат на странице, то вам нужно использовать метод .
В простейшем случае вы можете вызвать метод следующим образом:
$('#myElement').load( url );
Данный пример делает запрос AJAX по адресу , получает разметку с сервера и замещает ею содержание элемента .
Также можно передать данные в запросе, также как и в методах и :
var data = { city: "Васюки", date: "20120318" }; $('#myElement').load( url, data );
Модифицируем наш пример с прогнозом погоды так, чтобы сервер создавал разметку для передаваемых данных. Затем вызовем метод для отображения полученной разметки на странице. Сначала сохраним следующую разметку в файле на сервере:
<h2>Прогноз погоды в Васюках</h2> <h3>18 марта 2012</h3> <p>Будет мерзко холодно, сыро и слякотно. Макисмальная температура: 1C.</p>
имитирует эффект выполнения скрипта на стороне сервера и возвращает разметку с прогнозом погоды.
Теперь сохраняем следующий код в файле в той же папке, что и :
<!doctype html> <html lang="ru"> <head> <title>Прогноз погоды</title> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> </head> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script> $( function() { $('#getForecast').click( function() { var data = { city: "Васюки", date: "20120318" }; $('#forecast').load( "getForecast.html", data ); } ); } ); </script> </head> <body> <button id="getForecast">Получить прогноз погоды</button> <div id="forecast"></div> </body> </html>
Пробуем запустить демонстрацию и наслаждаемся результатом работы запроса AJAX.
Вот как работает код примера:
- Страница содержит элемент с идентификатором , в котором будет размещаться разметка прогноза.
- Обработчик события для кнопки формирует данные для отправки на сервер.
- Затем обработчик выбирает и вызывает метод jQuery , передавая URL () и объект с данными.
- jQuery выполняет AJAX запрос к файлу . Когда браузер получает ответ , jQuery автоматически замещает содержание элемента полученной разметкой.
Одной из причин того, что метод легко использовать является то, что не нужно писать возвратную функцию для обработки ответа — jQuery все делает для вас. Но если вам требуется производить какие-нибудь действия после того, как разметка вставлена, вы можете передать «полноценную» возвратную функцию в качестве третьего аргумента методу .
Объект jqXHR
Метод ajax() возвращает объект jqXHR, который можно использовать для получения подробной информации о запросе и с которым можно взаимодействовать. Объект jqXHR представляет собой оболочку объекта XMLHttpRequest, составляющую фундамент браузерной поддержки Ajax.
При выполнении большинства операций Ajax объект jqXHR можно просто игнорировать, что я и рекомендую делать. Этот объект используется в тех случаях, когда необходимо получить более полную информацию об ответе сервера, чем та, которую удается получить иными способами. Кроме того, его можно использовать для настройки параметров Ajax-запроса, но это проще сделать, используя настройки, доступные для метода ajax(). Свойства и методы объекта jqXHR описаны в таблице ниже:
Свойство/метод | Описание |
---|---|
readyState | Возвращает индикатор хода выполнения запроса на протяжении всего его жизненного цикла, принимающий значения от 0 (запрос не отправлен) до 4 (запрос завершен) |
status | Возвращает код состояния HTTP, отправленный сервером |
statusText | Возвращает текстовое описание кода состояния |
responseXML | Возвращает ответ в виде XML (если он является XML-документом) |
responseText | Возвращает ответ в виде строки |
setRequest(имя, значение) | Возвращает заголовок запроса (это можно сделать проще с помощью параметра headers) |
getAllResponseHeaders() | Возвращает в виде строки все заголовки, содержащиеся в ответе |
getResponseHeaders(имя) | Возвращает значение указанного заголовка ответа |
abort() | Прерывает запрос |
Объект jqXHR встречается в нескольких местах кода. Сначала он используется для сохранения результата, возвращаемого методом ajax(), как показано в примере ниже:
В этом примере мы сохраняем результат, возвращаемый методом ajax(), а затем используем метод setInterval() для вывода информации о запросе каждые 100 мс
Использование результата, возвращаемого методом ajax(), не изменяет того факта, что запрос выполняется асинхронно, поэтому при работе с объектом jqXHR необходимо соблюдать меры предосторожности. Для проверки состояния запроса мы используем свойство readyState (завершению запроса соответствует значение 4) и выводим ответ сервера на консоль
Для данного сценария консольный вывод выглядит так (в вашем браузере он может выглядеть несколько иначе):
Я использую объект jqXHR лишь в редких случаях и не делаю этого вообще, если он представляет собой результат, возвращаемый методом ajax(). Библиотека jQuery автоматически запускает Ajax-запрос при вызове метода ajax(), и поэтому я не считаю возможность настройки параметров запроса сколько-нибудь полезной. Если я хочу работать с объектом jqXHR (как правило, для получения дополнительной информации об ответе сервера), то обычно делаю это через параметры обработчика событий, о которых мы поговорим далее. Они предоставляют мне информацию о состоянии запроса, что избавляет от необходимости выяснять его.
2 AJAX POST Example, the jQuery way
So let’s get our hands dirty. Here’s our HTML5 and jQuery:
Let’s break down the not-so-clear parts of the method. The setting controls how data we receive from the server is treated. So if we want JSON from the server to be treated as text in our Javascript on the client side, for example, then we set this value as . If we don’t set the value at all, jQuery will try to figure out what the server sent and convert it intelligently. If it thinks it’s JSON, it’ll turn it into a JavaScript object; if it thinks it XML it’ll turn it into a native XMLDocument JavaScript object, and so on.
Next up is , which is the HTTP verb that we want to use. I’ll let you in on a little secret: since jQuery 1.9.0, you can use instead of . It could make things a little bit clearer for newcomers.
Following is . This is where understanding how HTTP requests and responses work helps a lot. What we set here gets sent as part of the HTTP header field . That’s important to note because we’re letting the server know ahead of time what type of content we’re sending, which allows the server to interpret the response correctly. For example, if you see a of you would know to process the content as JSON in your server-side code — it’s as simple as that.
Now, the setting is the data we’re going to send to the server. We can send data to the server in a variety of different formats, but the default is . That means we’ll be sending text to our server with our form data formatted in key-value pairs, like . Most, if not all, web server languages will pick up the key-value pairs and separate them for you either natively or through the use of libraries or frameworks.
Here’s how to do that in a few different languages:
- Ruby with Sinatra
- Python with web.py
- Node.JS with Express and body-parser middleware
Most POST requests from a form will use the content type. I’ll also provide an alternative if you need to POST actual JSON from jQuery — if, for instance, you need to make a call to your own RESTful API.
The method has several events we can hook into to handle our AJAX responses accordingly: , , , and . The ones we care about most are and , so we’ll use these in our example.
One important thing to note is that the data parameter for the function will be dependent on the setting. So it’s completely possible to treat JSON coming from the server as a string by setting to . Many developers, including myself, occasionally get tripped up attempting to output their request in the method and then wonder why nothing is showing up when they try to render JSON as HTML, which doesn’t work at all.
As long as you know that the parameter can be transformed into a different data type, fixing that problem will be easy. If your AJAX server responses for the form will always be of one type — for instance, JSON — and you will always treat it as JSON, then it makes sense to set to . If you need to juggle between different data types, omit to allow jQuery to intelligently convert the data.
Our function is where we do things after we get a successful AJAX response, like updating a message in our page or search results in a table. Here is a good live example of jQuery AJAX and POST from one of my clients, a free keyword suggestion tool for advanced SEO marketers.
Now, on to the server side. From the client side, all we need to worry about is sending the right Content Type and Request body (the content we send along like the form data). On the server side we pick this up, process it, and respond accordingly.
It’s important to note that we need to format the response data correctly according to the we want to send back. If we want to send a simple text message we would respond with . If we want to respond with JSON, we’ll send a and a properly formatted JSON string without any extra characters before or after the string, like so:
This will allow jQuery to convert the string into JSON. Please do not try to build a JSON string manually; use your language’s built-in JSON function or libraries to do it for you. Trust me, it will save you time and headaches.
2.1 Server side code for our AJAX form
If you’re running PHP 5.4 or above, you can fire up a server by going into your terminal running the following commands:
If you’re on Mac, install Mac Ports and then php55 with:
Then run the development server:
Now open up your browser to http://localhost:8111.
Опции $.ajax
А теперь, попрактиковавшись немного, расскажу теор.часть — про опции JQuery Ajax
-
async (true или false). По умолчанию true. Включает или
выключает асинхронные запросы (см. компонент xmlHttpRequest). Помните,
что включив синхронные запросы, можете подвесить браузер! - cache (true или false). Включает или выключает кеширование браузером
- contentType (строка). Тип содержания, передаваемого на сервер. При сабмите форм используйте application/x-www-form-urlencoded
- data (строка). Данные, отправляемые на сервер.
-
dataType (строка). Тип ожидаемых от сервера данных. Если
ничего не указано, JQuery попытается определить результат, основанный на
MIME-типе ответа. Может принимать значения: xml, json, script, html. -
ifModified (true или false (по умолчанию)). Если установлено в
true, то запрос будет успешным только тогда, когда ответ изменился с
момента прошлого запроса (достигается путём проверки заголовка
Last-Modified) - timeout (в милисекундах). Значение, по прошествии которого, соединение с сервером будет обрываться (таймаут)
- type (строка: GET или POST). Тип запроса к серверу: GET или POST
- url (строка). Страница сервера, к которой будет сделан запрос.
Вот мы и разобрались с Ajax на JQuery. Ождайте следующую статью — в ней будет рассмотрено что-то вкусненькое на JQuery 😉
Загрузка части страницы
Иногда сервер может вернуть больше разметки, чем нужно. Например, вы запрашиваете статью с сервера, чтобы вставить текст на свою страницу, но весь документ вам не нужен.
Метод jQuery позволяет легко ограничивать объем полученной разметки. Нужно просто добавить пробел после запроса URL, за которым будет следовать селектор для выбора нужной части страницы. jQuery получит всю страницу через AJAX, но только нужная часть разметки будет вставлена в текущий код.
Например:
$('#articleContainer').load( "newArticle.html #articleBody" );
Так можно получать новые страницы с сервера. Не нужно будет перегружать каждый раз страницу. Также можно выводить сообщение о загрузке для посетителя, чтобы он был в курсе происходящего. Например, можно добавить сообщение»Загрузка, подождите!» в контейнер , затем вызвать метод чтобы загрузить новое содержание в . Как только новая разметка будет получена , сообщение будет автоматически замещено.
Настройка и фильтрация Ajax-запросов
После того как вы познакомились с методом ajax() и доступными для работы с ним параметрами, мы можем рассмотреть несколько дополнительных методов, предоставляемых jQuery для упрощения настройки запросов.
Определение параметров, используемых по умолчанию
Метод ajaxSetup() позволяет установить значения параметров, которые будут применяться по умолчанию во всех Ajax-запросах, тем самым освобождая вас от необходимости настраивать параметры при каждом запросе. Пример использования этого метода приведен ниже:
Метод ajaxSetup() вызывается с помощью функции jQuery $ аналогично тому, как это делалось в случае вызова метода ajax(). Аргументом метода ajaxSetup() является объект, содержащий значения параметров, которые вы хотите использовать по умолчанию для всех Ajax-запросов. В этом примере мы устанавливаем значения по умолчанию для параметров timeout, global, error и converters.
После того как был вызван метод ajaxSetup(), нам остается определить значения лишь те значения параметров, которые мы хотим изменить, или те, которые не предоставляются по умолчанию. Это обеспечивает значительную экономию времени в тех случаях, когда приходится делать множество запросов с одинаковыми значениями параметров.
Фильтрация запросов
Метод ajaxSetup() определяет базовые значения конфигурационных параметров, применимые ко всем запросам Ajax. Возможности динамической настройки параметров для отдельных Ajax-запросов обеспечиваются методом ajaxPrefilter(). Пример использования этого метода приведен ниже:
Указанная вами функция будет выполняться для каждого нового Ajax-запроса. Аргументами, передаваемыми функции, являются параметры запроса (включая любые значения по умолчанию, установленные вами с помощью метода ajaxSetup()), а также исходные параметры, переданные методу ajax() (исключая любые значения по умолчанию) и объекту jqXHR запроса.
Мы вносим изменения в объект, передаваемый в качестве первого аргумента, как показано в примере. В данном сценарии, если среди параметров, передаваемых методу ajax(), присутствует параметр dataType, то длительность тайм-аута устанавливается равной двум секундам. Чтобы предотвратить отправку всех остальных запросов, для объекта jqXHR вызывается метод abort().
Ответ: status, statusText, responseText
Основные свойства, содержащие ответ сервера:
status HTTP-код ответа: 200 , 404 , 403 и так далее. Может быть также равен 0 , если сервер не ответил или при запросе на другой домен. statusText Текстовое описание статуса от сервера: OK , Not Found , Forbidden и так далее. responseText Текст ответа сервера.
Есть и ещё одно свойство, которое используется гораздо реже:
Если сервер вернул XML, снабдив его правильным заголовком Content-type: text/xml , то браузер создаст из него XML-документ. По нему можно будет делать запросы xhr.responseXml.querySelector(«. «) и другие.
Оно используется редко, так как обычно используют не XML, а JSON. То есть, сервер возвращает JSON в виде текста, который браузер превращает в объект вызовом JSON.parse(xhr.responseText) .
Преимущества технологии AJAX
Сокращение трафика. Объем данных при работе с web-приложениями значительно снижается. Это происходит за счет того, что не нужно загружать всю страницу целиком, достаточно получить только измененную часть либо набор данных. После этого JavaScript изменяет содержимое страницы в браузере.
Снижение нагрузки на сервер. Грамотное использование AJAX позволяет многократно уменьшить нагрузку на сервер. Например, можно использовать шаблон для создания постоянных элементов сайта: логотипа, меню и т. п. Кроме того, для удовлетворения конкретного запроса не нужно обновлять всю страницу. Например, при голосовании на сайте пользователь выбирает нужный пункт, нажимает кнопку, информация отправляется на сервер, после чего приходит ответ. В течение всего этого времени обновления страницы не происходит.
Увеличение скорости работы сервиса. Поскольку подгружается только содержательная часть, пользователь намного быстрее видит результат своих действий.
Широкий спектр возможностей. Использование AJAX не ограничивается формами. Например, при прохождении регистрации на некоторых сервисах пользователь вводит логин – и через мгновение ему выдается информация о том, свободен он или нет. Также при введении поискового запроса в Google после каждой буквы или слова предлагается несколько вариантов запроса. Это значительно повышает комфорт работы с сайтами.
Description
When making an Ajax request to the server, DataTables will construct a data object internally, with the data it requires to be sent to the server for the request. What this data contains will depend upon the processing mode DataTables is operating in:
- For client-side processing no additional data is submitted to the server
- For server-side processing () the draw request parameters are submitted — see the server-side processing manual.
The option provides the ability to add additional data to the request, or to modify the data object being submitted if required.
In principle it operates in exactly the same way as jQuery’s property, in that it can be given as an object with parameters and values to submit, but DataTables extends this by also providing it with the ability to be a function, to allow the data to be re-evaluated upon each Ajax request (see above).
Как прочитать данные в формате JSON с помощью jQuery
4.1 Показать товары на странице при загрузке
В папке products откройте файл read-products.js
Следующий код вызовет метод showProducts() при первой загрузке веб-страницы.
Функция showProducts() покажет список продуктов в виде HTML-таблицы. Поместите следующий код в файл read-products.js.
4.2 Показать товары при клике на кнопку
Следующий код вызовет метод showProducts() при нажатии кнопки с классом кнопки read-products-button.
Кнопку можно найти в HTML-шаблонах «Создать товар и «Обновить товар. Мы увидим это в следующих разделах.
Поместите следующий код под showProducts(); предыдущего раздела.
4.3 Создание функции showProducts()
Теперь мы создадим метод showProducts(). Замените комментарий // здесь будет метод showProducts() в файле read-products.js следующим кодом.
4.4 Получение списка товаров
Следующий код свяжется с нашим API, чтобы получить список продуктов в формате JSON. Поместите следующий код после открывающей фигурной скобки предыдущего раздела.
4.5 Создание кнопки «Добавить товар»
Мы должны добавить кнопку «Создать продукт» в списке товаров. Мы заставим эту кнопку работать позже в этом руководстве.
Поместите следующий код после открывающей фигурной скобки предыдущего раздела.
4.6 Создание HTML-таблицы
Мы должны начать строить HTML-таблицу, в которой появится список продуктов.
Следующий код создаст HTML-таблицу с ее заголовком. Разместите его после кода предыдущего раздела.
4.7 Построение строки таблицы для каждой записи
Мы пройдемся по каждой записи, возвращаемой API. Для каждой записи мы создадим строку таблицы.
Помимо данных о товаре, строка таблицы также будет иметь кнопки «Действие». К ним относятся кнопки «Просмотр», «Редактировать» и «Удалить».
Замените комментарий // здесь будут строки следующим кодом.
4.8 Вставка контента на страницу
Мы должны сделать так, чтобы HTML-таблица появилась на нашей веб-странице. Мы сделаем это, выводя таблицу в div page-content.
Поместите следующий код после закрывающего тега table
4.9 Изменение заголовка страницы
Следующий код изменит «заголовок» на веб-странице и «заголовок» на вкладке браузера.
Поместите следующий код после кода предыдущего раздела.
Настройка базовых параметров Ajax-запросов
Существует группа параметров, с помощью которых можно выполнить базовую настройку Ajax-запроса (некоторые из них, url и type, мы рассмотрели выше). Из всех доступных параметров они представляют наименьший интерес, и их имена в основном говорят сами за себя. Параметры, о которых идет речь, приведены в таблице ниже:
Параметр | Описание |
---|---|
accepts | Устанавливает для запроса значение заголовка Accept, который указывает MIME-типы, поддерживаемые браузером. По умолчанию это значение определяется параметром dataType |
cache | Значение false указывает на то, что содержимое запроса не должно кэшироваться сервером. По умолчанию кешируются все типы данных, кроме script и jsonp |
contentType | Устанавливает для запроса значение заголовка content-туре |
dataType | Указывает, какие типы данных ожидаются от сервера. Если используется этот параметр, то jQuery будет игнорировать информацию, предоставляемую сервером о типе запроса |
headers | Задает дополнительные заголовки и значения, которые должны включаться в запрос |
jsonp | Задает строку, которую следует использовать вместо функции обратного вызова при выполнении запросов JSONP (кроссдоменные запросы). Этот параметр требует согласования с сервером |
jsonpCallback | Задает имя функции обратного вызова, которое должно использоваться вместо автоматически сгенерированного случайного имени, используемого jQuery по умолчанию |
password | Задает пароль, который должен использоваться в запросе при прохождении процедуры аутентификации |
scriptCharset | Указывает jQuery, какой набор символов используется при кодировании запрашиваемого JavaScript-содержимого |
timeout | Задает длительность тайм-аута (в миллисекундах) для запроса |
userName | Задает имя пользователя, которое должно использоваться в запросе при прохождении процедуры аутентификации |
Задание тайм-аутов и заголовков
О том, что выполняются Ajax-запросы, пользователи часто даже не догадываются, и поэтому указание допустимой длительности тайм-аута — неплохая идея, поскольку это избавит пользователей от томительного ожидания завершения какого-то неведомого для них процесса. Пример задания тайм-аута для запроса приведен ниже:
В этом примере параметр timeout устанавливает максимальную длительность тайм-аута, равную 5 сек. Если запрос за это время не будет выполнен, то вызовется функция, заданная с помощью параметра error, и будет выведен код ошибки, определяемый параметром status.
Таймер запускается сразу же после передачи запроса браузеру, и большинство браузеров налагают ограничения на количество одновременно выполняющихся запросов. Это означает, что существует риск того, что к моменту истечения тайм-аута запрос даже не будет запущен. Чтобы избежать этого, необходимо располагать сведениями об ограничениях браузера, а также об объеме и ожидаемой длительности любых других выполняющихся Ajax-запросов.
Дополнительно в этом примере ниже используется параметр headers, с помощью которого в запрос добавляется заголовок. Для указания заголовков используется объект отображения данных. Используемый здесь заголовок может быть полезным для создания веб-приложений, поддерживающих архитектурный стиль REST, если только сервер правильно его распознает.
Types
object
- Description:
-
As an object, the option is used to extend the data object that DataTables constructs internally to submit to the server. This provides an easy method of adding additional, static, parameters to the data to be sent to the server. For dynamically calculated values, use as a function (see below).
function ajax.data( data, settings )
- Description:
-
As a function, the option can be used to modify the data DataTables submits to the server upon an Ajax request, by manipulating the original data object DataTables constructs internally, or by replacing it completely.
This provides the ability to submit additional information to the server upon an Ajax request, with the function being executed upon each Ajax request, allowing values to be dynamically calculated. For example, a value could be read from a text input field to act as an additional search option.
- Parameters:
- Returns:
-
, ,
If there is no return value from the function (i.e. ) then the original data object passed into the function by DataTables will be used for the request (the function may have manipulated its values).
If an object is returned, then that object will be used as the data for the request. It will not be merged with the original data object constructed by DataTables before being sent.
If a string is returned, this string it will be used in the Ajax request body rather than individual HTTP parameters being sent. This is particularly useful for sending JSON encoded data in the request body so the server can decode it directly, rather than individual HTTP parameters being sent. See example below for how to use to achieve this.
Синхронные и асинхронные запросы
Если в методе open установить параметр async равным false , то запрос будет синхронным.
Синхронные вызовы используются чрезвычайно редко, так как блокируют взаимодействие со страницей до окончания загрузки. Посетитель не может даже прокручивать её. Никакой JavaScript не может быть выполнен, пока синхронный вызов не завершён – в общем, в точности те же ограничения как alert .
Если синхронный вызов занял слишком много времени, то браузер предложит закрыть «зависшую» страницу.
Из-за такой блокировки получается, что нельзя отослать два запроса одновременно. Кроме того, забегая вперёд, заметим, что ряд продвинутых возможностей, таких как возможность делать запросы на другой домен и указывать таймаут, в синхронном режиме не работают.
Из всего вышесказанного уже должно быть понятно, что синхронные запросы используются чрезвычайно редко, а асинхронные – почти всегда.
Для того, чтобы запрос стал асинхронным, укажем параметр async равным true .
Если в open указан третий аргумент true (или если третьего аргумента нет), то запрос выполняется асинхронно. Это означает, что после вызова xhr.send() в строке (1) код не «зависает», а преспокойно продолжает выполняться, выполняется строка (2) , а результат приходит через событие (3) , мы изучим его чуть позже.
Полный пример в действии:
Событие readystatechange происходит несколько раз в процессе отсылки и получения ответа. При этом можно посмотреть «текущее состояние запроса» в свойстве xhr.readyState .
В примере выше мы использовали только состояние 4 (запрос завершён), но есть и другие.
Запрос проходит их в порядке 0 → 1 → 2 → 3 → … → 3 → 4 , состояние 3 повторяется при каждом получении очередного пакета данных по сети.
Пример ниже демонстрирует переключение между состояниями. В нём сервер отвечает на запрос digits , пересылая по строке из 1000 цифр раз в секунду.
При состоянии readyState=3 (получен очередной пакет) мы можем посмотреть текущие данные в responseText и, казалось бы, могли бы работать с этими данными как с «ответом на текущий момент».
Однако, технически мы не управляем разрывами между сетевыми пакетами. Если протестировать пример выше в локальной сети, то в большинстве браузеров разрывы будут каждые 1000 символов, но в реальности пакет может прерваться на любом байте.
Чем это опасно? Хотя бы тем, что символы русского языка в кодировке UTF-8 кодируются двумя байтами каждый – и разрыв может возникнуть между ними.
Получится, что при очередном readyState в конце responseText будет байт-полсимвола, то есть он не будет корректной строкой – частью ответа! Если в скрипте как-то по-особому это не обработать, то неизбежны проблемы.
Использование вспомогательных методов для работы с конкретными типами данных
Библиотека jQuery предоставляет три вспомогательных метода, которые делают работу с некоторыми типами данных более удобной. Некоторые из них мы рассмотрим далее.
Получение HTML-фрагментов
Метод load() предназначен для получения только HTML-данных, что позволяет совместить запрос HTML-фрагмента, обработку ответа от сервера для создания набора элементов и вставку этих элементов в документ в одном действии. Пример использования метода load() представлен ниже:
В этом сценарии мы вызываем метод load() для элемента, в который хотим вставить новые элементы, и передаем ему URL-адрес в качестве аргумента. Если запрос завершается успешно, а полученный от сервера ответ содержит действительный HTML-фрагмент, элементы вставляются в указанное место в документе, как показано на рисунке:
Вы видите, что все элементы из файла flowers.html добавлены в документ, как мы и хотели, но поскольку у них отсутствует атрибут class, то они не укладываются в табличную компоновку страницы, используемую в основном документе. Поэтому метод load() наиболее полезен в тех случаях, когда все элементы могут быть вставлены в одно место в документе без какой-либо дополнительной обработки.
Получение и выполнение сценариев
Метод getScript() загружает файл JavaScript, а затем выполняет содержащиеся в нем инструкции. Чтобы продемонстрировать работу этого метода, я создал файл myscript.js и сохранил его вместе с файлом test.html на своем веб-сервере. Содержимое этого файла представлено в примере ниже:
Эти инструкции генерируют три ряда элементов, описывающих цветы. Мы обошлись здесь без определения шаблонов и использовали циклы для генерации элементов (хотя, вообще говоря, следовало бы воспользоваться шаблонами данных).
Самое важное, что необходимо знать при работе со сценариям, — между инициализацией Ajax-запроса и выполнением инструкций сценария состояние документа может измениться. В примере ниже приведен сценарий из основного документа, в котором по-прежнему используется метод getScript(), но при этом, еще до завершения Ajax-запроса, модифицируется дерево DOM:. Здесь мы вызываем метод getScript() для основной функции $() и передаем ему в качестве аргумента URL-адрес файла, который хотим использовать
Если сервер способен предоставить указанный файл и этот файл содержит действительный JavaScript-код, то последний будет выполнен
Здесь мы вызываем метод getScript() для основной функции $() и передаем ему в качестве аргумента URL-адрес файла, который хотим использовать. Если сервер способен предоставить указанный файл и этот файл содержит действительный JavaScript-код, то последний будет выполнен.
Метод getScript() можно использовать для загрузки любых сценариев, но особенно полезно использовать его для загрузки и выполнения таких сценариев, как сценарии для отслеживания статистики посещения сайтов или определения географического местоположения клиента, которые не связаны с поддержкой основной функциональности веб-приложения. Пользователя не особенно заботит, в состоянии ли мы точно определять его местоположение для ведения статистики, тогда как длительное ожидание загрузки и выполнения сценария будет действовать ему на нервы.
Используя метод getScript(), можно быстро получать запрашиваемую информацию, не доставляя пользователям неудобств, вызванных необходимостью ожидания ответа. Уточню свою мысль. Я вовсе не предлагаю вам использовать этот метод для выполнения каких-либо действий скрытно от пользователя и говорю лишь о том, что следует отодвигать на второй план загрузку и выполнение вполне законной функциональности, если она представляет для пользователей меньшую ценность, чем затрачиваемое на ее ожидание время.
В данном примере после запуска Ajax-запроса с помощью метода getScript() из документа удаляется элемент row2, для чего используется метод remove(). Данный элемент используется в файле myscript.js для вставки новых элементов. Эти элементы отбрасываются незаметным для пользователя образом, поскольку в документе селектору #row2 ничто не соответствует. Итоговый результат представлен на рисунке:
Отнеситесь к этому примеру как к одному из образцов надежного дизайна для ситуаций, в которых документ подвергается изменениям. Во всяком случае запомните, что при написании внешних сценариев JavaScript не стоит делать слишком много допущений о состоянии документа.
Получение данных в формате JSON
Для загрузки данных JSON с сервера предназначен метод getJSON(). Возможно, это наименее полезный из всех трех вспомогательных методов, поскольку он не делает с данными ничего сверх того, что делает базовый метод get().
IE8,9: XDomainRequest
В IE8 и IE9 поддержка XMLHttpRequest ограничена:
- Не поддерживаются события, кроме onreadystatechange .
- Некорректно поддерживается состояние readyState = 3 : браузер может сгенерировать его только один раз во время запроса, а не при каждом пакете данных. Кроме того, он не даёт доступ к ответу responseText до того, как он будет до конца получен.
Дело в том, что, когда создавались эти браузеры, спецификации были не до конца проработаны. Поэтому разработчики браузера решили добавить свой объект XDomainRequest , который реализовывал часть возможностей современного стандарта.
А обычный XMLHttpRequest решили не трогать, чтобы ненароком не сломать существующий код.
Мы подробнее поговорим про XDomainRequest в главе XMLHttpRequest: кросс-доменные запросы. Пока лишь заметим, что для того, чтобы получить некоторые из современных возможностей в IE8,9 – вместо new XMLHttpRequest() нужно использовать new XDomainRequest .
Теперь в IE8,9 поддерживаются события onload , onerror и onprogress . Это именно для IE8,9. Для IE10 обычный XMLHttpRequest уже является полноценным.
IE9- и кеширование
Обычно ответы на запросы XMLHttpRequest кешируются, как и обычные страницы.
Но IE9- по умолчанию кеширует все ответы, не снабжённые антикеш-заголовком. Другие браузеры этого не делают. Чтобы этого избежать, сервер должен добавить в ответ соответствующие антикеш-заголовки, например Cache-Control: no-cache .
Впрочем, использовать заголовки типа Expires , Last-Modified и Cache-Control рекомендуется в любом случае, чтобы дать понять браузеру (не обязательно IE), что ему следует делать.
Альтернативный вариант – добавить в URL запроса случайный параметр, предотвращающий кеширование.
Например, вместо xhr.open(‘GET’, ‘service’, false) написать:
По историческим причинам такой способ предотвращения кеширования можно увидеть много где, так как старые браузеры плохо обрабатывали кеширующие заголовки. Сейчас серверные заголовки поддерживаются хорошо.
Examples
Get JSON data from a file via Ajax.:
Get JSON data from a file via Ajax, using to change to (i.e. ):
Get JSON data from a file via Ajax, using to read data from a plain array rather than an array in an object:
Send request as POST:
Add data to the request, returnng an object by extending the default data:
Add data to the request by manipulating the data object:
Manipulate the data returned from the server — add a link to data (note this can, should, be done using for the column — this is just a simple example of how the data can be manipulated).:
Get the data from localStorage (could interface with a form for adding, editing and removing rows).: