Пример AJAX GET запроса
В качестве примера напишем асинхронный AJAX запрос на чистом JavaScript, который будет при нажатии на кнопку обновлять содержимое списка на странице.
1. Для генерации данных на сервере создадим простой php-файл, который будет возвращать массив из 3 элементов в формате JSON.
В качестве сервера можно использовать «Open Server Panel», встроенный в PHP веб-сервер или любой другой.
2. Создадим HTML файл и поместим в следующее содержимое:
В этом примере:
- при нажатии на кнопку вызывается функция ;
- эта функция создаёт AJAX запрос и отправляет его на «», после получения ответа обновляет содержимое элемента «»;
- для преобразования JSON в массив используется метод ;
- изменение содержимого «» выполняется с помощью .
Что такое асинхронный запрос AJAX
Технология AJAX в основном используется для создания асинхронных запросов к серверу. Асинхронный запрос — это такой
запрос, который выполняется в фоновом режиме и не мешает пользователю взаимодействовать со страницей.
При отправке асинхронного запроса, браузер (страница) не «замораживается», т.е. с ней, как и прежде, можно работать.
Но тогда как узнать, когда придёт ответ с сервера. Чтобы это определить, необходимо отслеживать свойство браузера
(состояние готовности). Данное свойство содержит число, по значению которого можно судить о
том, в какой стадии находится запрос. В следующей таблице приведены основные значения свойства
и соответствующие им состояния.
Значение свойства readyState | Описание |
---|---|
запрос не инициализирован | |
1 | выполнена настройка запроса |
2 | запрос отправлен |
3 | запрос находится в процессе обработки на сервере |
4 | запрос завершён |
Т.е. получается, что нам необходимо отследить, когда значение у свойства будет равно 4. Это
будет означать то, что на отправленный запрос, пришёл ответ с сервера. Остальные значения на практике используются
довольно редко, и некоторые браузеры могут их не поддерживать.
Для того чтобы определить на какой стадии находится запрос, необходимо использовать событие объекта XMLHttpRequest
. Данное событие происходит каждый раз, когда изменяется значение свойства
. Следовательно, в обработчике этого события (неименованной или именованной функции) можно
прописать действия, которые будут проверять равно ли данное свойство 4 и если равно, то например, вывести ответ
сервера на страницу.
jQuery.get( url [, data ] [, success ] [, dataType ] )Возвращает: jqXHR
Описание: Загружает данные с сервера при помощи HTTP GET запроса
-
-
url
Тип:Строка содержащая URL-адрес куда будет отправлен запрос.
-
data
Тип: илиПлоский объект или строка, которая будет отправлена на сервер с запросом.
-
success
Тип: ( data, textStatus, jqXHR )
Функция обратного вызова, выполняемая если запрос успешен. Требуется если предоставлен , но Вы можете использовать значение или . -
dataType
Тип:Тип данных ожидаемый с сервера. Используются по умолчанию: xml, json, script, text, html в зависимости от заданного URL-адреса.
-
-
Ассоциативный массив (ключ/значение) настраивающий Ajax. Все поля кроме url не обязательны и могут быть установлены по умолчанию припомощи метода $.ajaxSetup(). Полный список параметров смотрите в описании метода jQuery.ajax( settings ). Метод запроса автоматически будет установлен в значение GET.
Это сокращенная функция Ajax, эквивалентна коду:
1 2 3 4 5 6 |
The callback function is passed the returned data, which will be an XML root element, text string, JavaScript file, or JSON object, depending on the MIME type of the response. It is also passed the text status of the response.
As of jQuery 1.5, the callback function is also passed a (in jQuery 1.4, it was passed the object). However, since JSONP and cross-domain GET requests do not use XHR, in those cases the and parameters passed to the success callback are undefined.
Most implementations will specify a success handler:
1 2 3 4 |
This example fetches the requested HTML snippet and inserts it on the page.
The jqXHR Object
As of jQuery 1.5, all of jQuery’s Ajax methods return a superset of the object. This jQuery XHR object, or «jqXHR,» returned by implements the Promise interface, giving it all the properties, methods, and behavior of a Promise (see Deferred object for more information). The (for success), (for error), and (for completion, whether success or error; added in jQuery 1.6) methods take a function argument that is called when the request terminates. For information about the arguments this function receives, see the section of the documentation.
The Promise interface also allows jQuery’s Ajax methods, including , to chain multiple , , and callbacks on a single request, and even to assign these callbacks after the request may have completed. If the request is already complete, the callback is fired immediately.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Deprecation Notice
The , , and callback methods are removed as of jQuery 3.0. You can use , , and instead.
- Due to browser security restrictions, most «Ajax» requests are subject to the same origin policy; the request can not successfully retrieve data from a different domain, subdomain, port, or protocol.
- If a request with jQuery.get() returns an error code, it will fail silently unless the script has also called the global .ajaxError() method. Alternatively, as of jQuery 1.5, the method of the object returned by jQuery.get() is also available for error handling.
- Script and JSONP requests are not subject to the same origin policy restrictions.
IE8,9: XDomainRequest
В IE8 и IE9 поддержка ограничена:
- Не поддерживаются события, кроме .
- Некорректно поддерживается состояние : браузер может сгенерировать его только один раз во время запроса, а не при каждом пакете данных. Кроме того, он не даёт доступ к ответу до того, как он будет до конца получен.
Дело в том, что, когда создавались эти браузеры, спецификации были не до конца проработаны. Поэтому разработчики браузера решили добавить свой объект , который реализовывал часть возможностей современного стандарта.
А обычный решили не трогать, чтобы ненароком не сломать существующий код.
Мы подробнее поговорим про в главе XMLHttpRequest: кросс-доменные запросы. Пока лишь заметим, что для того, чтобы получить некоторые из современных возможностей в IE8,9 – вместо нужно использовать .
Кросс-браузерно:
Теперь в IE8,9 поддерживаются события , и . Это именно для IE8,9. Для IE10 обычный уже является полноценным.
Обычно ответы на запросы кешируются, как и обычные страницы.
Но IE9- по умолчанию кеширует все ответы, не снабжённые антикеш-заголовком. Другие браузеры этого не делают. Чтобы этого избежать, сервер должен добавить в ответ соответствующие антикеш-заголовки, например .
Впрочем, использовать заголовки типа , и рекомендуется в любом случае, чтобы дать понять браузеру (не обязательно IE), что ему следует делать.
Альтернативный вариант – добавить в URL запроса случайный параметр, предотвращающий кеширование.
Например, вместо написать:
По историческим причинам такой способ предотвращения кеширования можно увидеть много где, так как старые браузеры плохо обрабатывали кеширующие заголовки. Сейчас серверные заголовки поддерживаются хорошо.
метод прерывания
После отправки запроса, если вы хотите завершить его, вы можете вызвать метод прерывания, который определяется следующим образом:
Обратный вызов события XHR
Когда XHR отправляет асинхронный запрос, мы не можем знать, является ли запрос ненормальным, когда запрос поступает на сервер и когда сервер возвращает данные ответа. XHR предоставляет нам множество обратных вызовов событий, чтобы уведомить нас об изменениях в статусе запроса и ответа. Следующий язык определения интерфейса описывает следующее。
Атрибут readyState используется для описания состояния XHR. Он имеет следующие пять состояний:
значение | положение дел | описание |
---|---|---|
UNSENT | Самое начальное состояние, открытый метод не вызывался | |
1 | OPENED | Открытый метод был вызван |
2 | HEADERS_RECEIVED | Метод отправки был вызван, и можно получить заголовок HTTP и статус ответа. |
3 | Загрузка данных, загруженные данные не завершены | |
4 | DONE | Загрузка данных завершена |
Атрибут onreadystatechange может определять функцию обратного вызова, которая будет вызываться при изменении состояния XHR (т. Е. ReadyState). Вы можете использовать эту функцию обратного вызова, чтобы определить, успешен ли запрос.
Атрибут загрузки представляет процесс загрузки данных. Это экземпляр XMLHttpRequestUpload. XMLHttpRequestUpload наследует интерфейс XMLHttpRequestEventTarget. XMLHttpRequestEventTarget имеет 7 методов обратного вызова. Соответствующий метод будет вызываться в процессе загрузки данных. XHR также наследует интерфейс XMLHttpRequestEventTarget, поэтому он также имеет эти методы обратного вызова, но большинство его методов обратного вызова запускаются в процессе загрузки данных ответа с сервера.
Как добавить методы обратного вызова событий
Как видно из приведенного выше определения, интерфейсы событий унаследованы от EventTarget. Определение EventTarget выглядит следующим образом. Существует метод addEventListener. Первый параметр — это имя события без префикса «on». Второй параметр — это обратный вызов. метод и другие параметры.
Таким образом, следующий код дает тот же эффект, что и первый метод.
XHR ответ
После понимания запросов XHR и обратных вызовов событий XHR остается работа по обработке ответов XHR, такая как анализ данных и т. Д. Для обработки ответов вам необходимо понимать следующие методы и атрибуты.
responseType, response, responseText, атрибуты responseXML
Вы можете установить responseType перед отправкой запроса, чтобы указать тип возвращаемых данных ответа.Существуют следующие типы responseType:
Типы | описание |
---|---|
empty string | Пустая строка, это значение по умолчанию |
arraybuffer | Двоичный буферный массив |
blob | Бинарный большой объект |
document | Тип документа |
json | Тип JSON |
text | Тип текста |
При обработке данных ответа вам необходимо определить тип возвращаемых данных на основе responseType. Когда responseType является текстом или пустой строкой, вы можете использовать свойство responseText. Когда responseType является другим типом, при вызове responseText будет возникать исключение; когда responseType является документом или пустым responseXML, исключение произойдет при вызове responseXML, когда responseType — это другие типы.Когда responseType не является пустой строкой, text Когда используется тип документа, его необходимо преобразовать в определенный тип для анализа.
Объект 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 (как правило, для получения дополнительной информации об ответе сервера), то обычно делаю это через параметры обработчика событий, о которых мы поговорим далее. Они предоставляют мне информацию о состоянии запроса, что избавляет от необходимости выяснять его.
Создание POST-запроса
Для задания требуемого типа запроса, который необходимо выполнить, используется параметр type. По умолчанию выполняются GET-запросы, как в предыдущем примере. Пример использования метода ajax() для создания POST-запроса и отправки данных формы на сервер приведен ниже:
Здесь я не буду подробно описывать этот пример, т.к. мы его рассмотрели подробно в предыдущей статье (только с использованием метода post()). Отмечу только, что здесь дополнительно к type мы использовали еще несколько параметров. Для указания цели POST-запроса используется описанный ранее параметр url. Пересылаемые данные указываются с помощью параметра data, значение которого устанавливается с помощью метода serialize(), описанного в предыдущей статье. Тип данных, получаемых от сервера указывается в параметре dataType.
Ограничения безопасности. Кросс-доменный XMLHttpRequest¶
Для ограничения XmlHttpRequest используется философия «Same Origin Policy». Она очень проста — каждый сайт в своей песочнице. Запрос можно делать только на адреса с тем же протоколом, доменом, портом, что и текущая страница.
Т. е., со страницы на адресе нельзя сделать XmlHttpRequest на адрес , или
Это создает проблему, если хочется взять контент с другого сайта. Как правило, в этом случае вместо XmlHttpRequest используются другие средства, например, загрузка через динамически создаваемый тег . Но, конечно, XmlHttpRequest удобнее.
Проксирование
Самый простой способ обойти это ограничение — проксирование. Допустим, мы хотим сделать запрос с на . Вместо указания в методе , там ставится URL вида . Запрос приходит на наш веб-сервер, проксирует его на сервер на , который уже обрабатывает этот запрос, как нужно.
Если находится на другом сервере, то серверу придется проксировать посетителю как запрос, так и ответ. При этом, разумеется, никак не будут задействованы куки , так что не получится отдельной авторизации, учета пользователей или что-то в этом роде с отдельными куками.
Например, при использовании web-сервера Apache, для проксирования нужны директивы , . Кроме того, доступны еще модули, которые по необходимости правят урлы, разархивируют контент и т. п.
Использование наддомена
Часто кроссбраузерные запросы — это
- Способ обойти ограничения в 2 одновременных соединения к одному домену-порту.
- Способ использовать два разных сервера в общении с посетителем. Например, на — чат-демон, на — веб-сервер.
Кросс-доменные запросы между наддоменами , (на общем ) допустимы при использовании свойства , которое надо установить в
Любые запросы допустимы между сайтами, находящимися в доверенной () зоне Internet Explorer. Так что, внутренний корпоративный портал может быть у всех пользователей в этой зоне, и он сможет делать запросы к любым сайтам.
XhrIframeProxy
Еще один хитрый подход называется XHRIframeProxy, и позволяет делать XmlHttpRequest к любым доменам при помощи хитрого iframe-хака. Он основан на том, что фреймы с разных доменов могут читать и менять друг у друга anchor, т.е часть адреса после решетки ». За счет этого организуется специальный протокол, по которому «проксируется» XmlHttpRequest.
Этот метод, в принципе, вполне жизнеспособен, особенно для небольшого объема данных.
Продвинутое использование
$.post() является сокращенным вариантом функции $.ajax(), вызванной со следующими параметрами:
$.ajax({ url url, type "POST", data data, success success, dataType dataType });
Подробности использования параметра dataType можно найти в описании .
Замечание: большинство браузеров не позволяют проводить ajax-запросы на ресурсы с доменами, поддоменами и протоколами, отличными от текущего. Однако, это ограничение не распространяется на запросы типа jsonp и script.
Обработка выполнения запроса
Стандартным средством обработки успешного выполнения запроса, является указание собственной функции в параметре success. При вызове она получает данные переданные сервером, текстовый статус выполнения запроса, а так же Объект jqXHR.
Начиная с jQuery-1.5, метод $.post() возвращает объект jqXHR, который помимо прочего реализует интерфейс deferred, что позволяет задавать дополнительные обработчики выполнения. Помимо стандартных для объекта deferred методов .done(), .fail() и .then(), с помощью которых можно устанавливать обработчики, в jqXHR реализованы .success(), .error() и .complete(). Это сделано для соответствия привычным названиям методов, с помощью которых устанавливаются обработчики выполнения ajax-запросов. Однако начиная с jQuery-1.8 эти три метода станут нежелательными для использования.
// Запустим ajax-запрос, установим обработчики его выполнения и // сохраним объект jqxhr данного запроса для дальнейшего использования. var jqxhr = $.post("example.php") .success(function() { alert("Успешное выполнение"); }) .error(function() { alert("Ошибка выполнения"); }) .complete(function() { alert("Завершение выполнения"); }); // какой-либо код... // установим еще один обработчик удачного выполнения запроса jqxhr.complete(function(){ alert("Успешное выполнения 2"); });
Основы
XMLHttpRequest имеет два режима работы: синхронный и асинхронный.
Сначала рассмотрим асинхронный, так как в большинстве случаев используется именно он.
Чтобы сделать запрос, нам нужно выполнить три шага:
-
Создать .
-
Инициализировать его.
Этот метод обычно вызывается сразу после . В него передаются основные параметры запроса:
- – HTTP-метод. Обычно это или .
- – URL, куда отправляется запрос: строка, может быть и объект URL.
- – если указать , тогда запрос будет выполнен синхронно, это мы рассмотрим чуть позже.
- , – логин и пароль для базовой HTTP-авторизации (если требуется).
Заметим, что вызов , вопреки своему названию, не открывает соединение. Он лишь конфигурирует запрос, но непосредственно отсылается запрос только лишь после вызова .
-
Послать запрос.
Этот метод устанавливает соединение и отсылает запрос к серверу. Необязательный параметр содержит тело запроса.
Некоторые типы запросов, такие как , не имеют тела. А некоторые, как, например, , используют , чтобы отправлять данные на сервер. Мы позже увидим примеры.
-
Слушать события на , чтобы получить ответ.
Три наиболее используемых события:
- – происходит, когда получен какой-либо ответ, включая ответы с HTTP-ошибкой, например 404.
- – когда запрос не может быть выполнен, например, нет соединения или невалидный URL.
- – происходит периодически во время загрузки ответа, сообщает о прогрессе.
Вот полный пример. Код ниже загружает с сервера и сообщает о прогрессе:
После ответа сервера мы можем получить результат запроса в следующих свойствах :
- Код состояния HTTP (число): , , и так далее, может быть в случае, если ошибка не связана с HTTP.
- Сообщение о состоянии ответа HTTP (строка): обычно для , для , для , и так далее.
- (в старом коде может встречаться как )
- Тело ответа сервера.
Мы можем также указать таймаут – промежуток времени, который мы готовы ждать ответ:
Если запрос не успевает выполниться в установленное время, то он прерывается, и происходит событие .
URL с параметрами
Чтобы добавить к URL параметры, вида , и корректно закодировать их, можно использовать объект URL:
Частые проблемы¶
Кеширование
Многие браузеры поддерживают кеширование ответов на XmlHttpRequest запросы. При этом реализации кеширования немного разные.
Например, при повторном XmlHttpRequest на тот же URL, Firefox посылает запрос с заголовком «» со значением, указанным в заголовке «» предыдущего ответа.
А Internet Explorer делает так, только когда кешированный ответ устарел, т. е. после времени из заголовка «Expires» предыдущего ответа. Поэтому, кстати, многие думают, что Internet Explorer вообще не очищает кеш ответов.
Самое простое решение проблемы — просто убрать кеширование. Например, при помощи заголовков, или добавлением случайного параметра в URL типа:
Есть, однако, ряд случаев, когда кеширование XMLHttpRequest браузером полезно, улучшает время ответа и экономит трафик.
Пример демонстрирует универсальный код работы с кешем для Internet Explorer и Firefox.
В Internet Explorer, если запрос возвращается из кеша без перепроверки, заголовок — пустая строка. Поэтому нужно сделать дополнительный запрос, который на самом деле никакой не дополнительный, т. к. текущий возвращен из кеша.
Ссылку на кешированый запрос сохраняем, т. к. если код ответа дополнительного запроса — «», то его тело станет пустой строкой («»), и нужно будет вернуться к кешированному объекту. Более эффективным, впрочем, будет не создавать новый объект , а сохранить данные из существующего и использовать заново его же.
Пример выше опирается на то, что сервер всегда выдает заголовок «», что верно для большинства конфигураций. В нем делается синхронный запрос. В асинхронном случае, проверка на Date и т. д. нужно делать после получения ответа в функции-обработчике .
Повторное использование объекта XmlHttpRequest
В Internet Explorer, если вызван после установки , может быть проблема с повторным использованием этого XmlHttpRequest.
Чтобы использовать заново XmlHttpRequest, сначала вызывайте метод , а затем — присваивайте . Это нужно потому, что IE неявно очищает объект XmlHttpRequest в методе , если его статус «».
Вызывать для перенаправления запроса на другой URL не нужно, даже если текущий запрос еще не завершился.
Утечки памяти
В Internet Explorer объект XmlHttpRequest принадлежит миру DOM/COM, а Javascript-функция — миру Javascript. Вызов r неявную круговую связь: ссылается на функцию через , а функция, через область видимости — видит (ссылается на) .
Невозможность обнаружить и оборвать такую связь во многих (до IE 6,7 редакции июня 2007?) версиях Internet Explorer приводит к тому, что XmlHttpRequest вместе с ответом сервера, функция-обработчик, и всё замыкание прочно оседают в памяти до перезагрузки браузера.
Чтобы этого избежать, ряд фреймворков (YUI, dojo…) вообще не ставят , а вместо этого через проверяют его каждые 10 миллисекунд. Это разрывает круговую связку <-> , и утечка памяти не грозит даже в самых глючных браузерах.
Использование XMLHTTPRequest¶
Различают два использования XmlHttpRequest. Первое — самое простое, синхронное.
Синхронный XMLHttpRequest
В этом примере через XMLHTTPRequest, с сервера запрашивается страница , и текст ответа сервера показывается через .
Здесь сначала создается запрос, задается открытие () синхронного соединение с адресом и запрос отсылается с , т. е. без данных: .
При синхронном запросе браузер «подвисает» и ждет на строчке 3, пока сервер не ответит на запрос. Когда ответ получен — выполняется строка 4, код ответа сравнивается с 200 (ОК), и при помощи печатается текст ответа сервера. Все максимально просто.
Свойство получит такой же текст страницы, как браузер, если бы Вы в перешли на . Для сервера GET-запрос через XmlHttpRequest ничем не отличается от обычного перехода на страницу.
Асинхронный XMLHttpRequest
Этот пример делает то же самое, но асинхронно, т. е. браузер не ждет выполнения запроса для продолжения скрипта. Вместо этого к свойству подвешивается функция, которую запрос вызовет сам, когда получит ответ с сервера.
Асинхронность включается третьим параметром функции . В отличие от синхронного запроса, функция не останавливает выполнение скрипта, а просто отправляет запрос.
Запрос регулярно отчитывается о своем состоянии через вызов функции . Состояние под номером 4 означает конец выполнения, поэтому функция-обработчик при каждом вызове проверяет — не настало ли это состояние.
Вообще, список состояний такой:
- — Unitialized
- — Loading
- — Loaded
- — Interactive
- — Complete
Состояния 0-2 вообще не используются.
Вызов функции с состоянием в теории должен происходить каждый раз при получении очередной порции данных от сервера. Это могло бы быть удобным для обработки ответа по частям, но Internet Explorer не дает доступа к уже полученной части ответа.
Firefox дает такой доступ, но для обработки запроса по частям состояние все равно неудобно из-за сложностей обнаружения ошибок соединения. Поэтому тоже не используется.
На практике используется только последнее, .
Если хотите углубиться в тонкости багов браузеров c , отличными от , то многие из них рассмотрены в статье на Quirksmode (англ.).
Не используйте синхронные запросы
Синхронные запросы применяются только в крайнем случае, когда кровь из носу необходимо дождаться ответа сервера до продолжения скрипта. В 999 случаях из 1000 можно использовать асинхронные запросы. При этом общий алгоритм такой:
- Делаем асинхронный запрос
- Рисуем анимированную картинку или просто запись типа «Loading…»
- В при достижении состояния 4 убираем и, в зависимости от вызываем обработку ответа или ошибки.
Кроме того, иногда полезно ставить ограничение на время запроса. Например, хочется генерировать ошибку, если запрос висит более 10 секунд.
Для этого сразу после через ставится вызов обработчика ошибки, который очищается при получении ответа и обрывает запрос с генерацией ошибки, если истекли 10 секунд.
Таймаут на синхронный запрос ставить нельзя, браузер может висеть долго-долго… А вот на асинхронный — пожалуйста.
Этот пример демонстрирует такой таймаут.
События ajax при успешном выполнении и ошибки
Использовать будем $.ajax(), перед тем как писать скрипт, не забываем подключать jQuery.
Основа нашего скрипта будет выглядеть так:
$('.price-table').on('click', '.btn-item-add', function(){ $.ajax({}); return false; });
В данном коде мы видим, что по клику на кнопку с классом .btn-item-add, у которой кстати должен быть родитель с классом .price-table, мы вызываем аякс (пока что безе параметров для более простого понимания). return false — дописываем на случай если наша кнопка сделана через тег <a>.
Теперь добавим события и базовые параметры:
//AJAX ADD TO CART $('.price-table').on('click', '.btn-item-add', function(){ var $id = $(this).data('id'), $thisBut = $(this), $count = $(this).prev('.quant-block').find('.pr-item-quant').val(); $.ajax({ url: '/include/ajax_cart.php', type: 'get', cache: false, data: 'id='+$id+'&count='+$count, }).done(function(data){ //смотрим какой ответ отправляется в случае успеха console.log(data); }).complete(function(){ // после того как аякс выполнился }).error(function(){ // пишем ошибку в консоль если что-то пошло не так console.log('There was an error'); }); return false; });
В самом начале добавились параметры, а для аякса прописали параметры: url, type, cache и data
Обратите внимание что мы передаем параметры, а в PHP $_GET в дальнейшем можно их обработать. Ссылку указываем относительно корня сайта
Для примера у нас есть 3 jQuery события — done, complete и error. Отличие done от complete лишь в том что done вызывается первым. Таким образом мы можем в первой функции выполнить запрос, а во второй делать что душе угодно .
Организация простой очереди асинхронных запросов на jQuery (троттлинг)
Классическим представлением организации троттлинга является простая очередь асинхронных запросов на jQuery. Строится она следующим образом. Вы создаете некий контейнер, в который помещаются запросы, и запускается одна функция, которая через определенный промежуток времени вызывает по одному запросу из ранее определенного контейнера (например, простой массив). Вот, код:
// Простая очередь $.qajaxSimple = function (url, options) { // Параметр в миллисекундах, когда необходимо запускать следующий ajax запрос var intervalTimeout = 100; // Определяем переменную для хранения очереди $._qajaxSimpleQueue = $._qajaxSimpleQueue || []; // Сохраняем параметры запроса $._qajaxSimpleQueue.push({ url: url, options: options }); // Определяем циклический запуск асинхронного запроса по времени // Или если функция уже определена, то созерцаем красоту присваивания переменной самой себе $._qajaxSimpleInterval = $._qajaxSimpleInterval || setInterval(function () { // Получаем первый запрос var params = $._qajaxSimpleQueue.shift(); // Если данные в запросе хранились, то запускаем ajax-запрос if(params) { $.ajax(params.url, params.options); } }, intervalTimeout); };
Так же изменим функцию formTestFor, чтобы наглядно увидеть результаты, и подкорректируем обработчик события загрузки DOM:
function formTestFor(selector, func) { $(selector + ' .start-process').click(function () { getFakeLoader(new Date(), selector + ' .row-1 td', func)(); getFakeLoader(new Date(), selector + ' .row-2 td', func)(); getFakeLoader(new Date(), selector + ' .row-3 td', func)(); getFakeLoader(new Date(), selector + ' .row-4 td', func)(); getFakeLoader(new Date(), selector + ' .row-5 td', func)(); getFakeLoader(new Date(), selector + ' .row-6 td', func)(); getFakeLoader(new Date(), selector + ' .row-7 td', func)(); getFakeLoader(new Date(), selector + ' .row-8 td', func)(); }); } $(function () { formTestFor('.left-table', $.qajaxSimple); formTestFor('.right-table'); });
Теперь, нажав на кнопку запуска процесса из левой таблицы, вы должны увидеть примерно следующее:
Примечание: Интервал задержки составлял 100 мс.
Как можно увидеть, теперь, запустив одновременно 8 асинхронных запросов, они будут распределены примерно в интервале от 0 до 1 секунды. Это хорошо, но не для всех случаев.
Во-первых, возможен вариант, что для запуска вашего запроса придется ждать все время простоя.
Во-вторых, если вам нужно запустить 10 запросов, то до запуска 10-го запроса придется ждать примерно 1 секунду (при текущем параметре 100 мс) — это несколько расточительно, особенно, если изначальная страница генерируется намного быстрее. Учитывайте, что это тестовые запросы, которые выполняются практически моментально. Конечно, вы можете подобрать оптимальный для вас интервал ожидания и вызывать запросы в нужном вам порядке, но все же это не тот результат, которого бы хотелось достичь (дополнительная ненужная задержка).
В-третьих, чаще всего, именно на первых этапах запускается большинство асинхронных запросов. Простая и обыденная ситуация. Открывается страница, на которой должны асинхронно загрузится 5-10 блоков. В последующем же, действия пользователей приводят всего к паре запросов, что уже не так сильно влияет на нагрузку. Ждать полсекунды секунду для запуска получения блоков не всегда имеет смысл.
Поэтому, неплохой мыслью было бы подкорректировать троттлинг функцию на jQuery таким образом, чтобы во временном интервале отправлялся не один ajax запрос, а сразу несколько.