Jquery синхронный ajax. Отправка асинхронных запросов на JQuery

У меня есть виджет JavaScript, который предоставляет стандартные точки расширения. Одна из них - это функция beforecreate . Он должен возвращать false чтобы предотвратить создание элемента.

Beforecreate: function (node, targetNode, type, to) { jQuery.get("http://example.com/catalog/create/" + targetNode.id + "?name=" + encode(to.inp.value), function (result) { if (result.isOk == false) alert(result.message); }); }

Но я хочу, чтобы мой виджет не создавал этот элемент, поэтому я должен возвращать false в функции mother, а не в обратном вызове. Есть ли способ выполнить синхронный запрос AJAX с использованием jQuery или любого другого API-интерфейса в браузере?

15 ответов

Вы можете установить jQuery Ajax в синхронном режиме, позвонив

JQuery.ajaxSetup({async:false});

Затем выполните ваши вызовы Ajax с помощью jQuery.get(...);

Затем просто включайте его снова

JQuery.ajaxSetup({async:true});

Я предполагаю, что это работает так же, как предложено @Adam, но может быть полезно кому-то, кто хочет перенастроить свои jQuery.get() или jQuery.post() в более сложный синтаксис jQuery.ajax() .

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

Function getWhatever() { // strUrl is whatever URL you need to call var strUrl = "", strReturn = ""; jQuery.ajax({ url: strUrl, success: function(html) { strReturn = html; }, async:false }); return strReturn; }

Все эти ответы не согласны с тем, что выполнение Ajax-вызова с помощью async: false приведет к зависанию браузера, пока не будет завершен запрос Ajax. Использование библиотеки управления потоками позволит решить эту проблему, не повесив браузер. Ниже приведен пример с Frame.js :

Beforecreate: function(node,targetNode,type,to) { Frame(function(next)){ jQuery.get("http://example.com/catalog/create/", next); }); Frame(function(next, response)){ alert(response); next(); }); Frame.init(); }

Имейте в виду, что если вы выполняете междоменный вызов Ajax (используя JSONP) - вы не можете делать он синхронно, флаг async будет игнорироваться jQuery.

$.ajax({ url: "testserver.php", dataType: "jsonp", // jsonp async: false //IGNORED!! });

Для JSONP-вызовов вы можете использовать:

  • Ajax-вызов в ваш собственный домен - и выполните междоменный вызов на стороне сервера
  • Измените свой код для работы асинхронно
  • Используйте библиотеку "секвенсер функций", такую ​​как Frame.js(этот ответ)
  • Заблокируйте пользовательский интерфейс вместо блокировки выполнения (этот ответ) (мой любимый способ)

Примечание: вы не должны использовать async: false из-за этого предупреждения:

Начиная с Gecko 30.0 (Firefox 30.0/Thunderbird 30.0/SeaMonkey 2.27), синхронные запросы в основном потоке устарели из-за негативных последствий для пользователя.

Chrome даже предупреждает об этом в консоли:

Синхронный XMLHttpRequest в основном потоке устарел из-за его пагубных последствий для конечного пользователя. Для получения дополнительной помощи, проверьте https://xhr.spec.whatwg.org/ .

Это может сломать вашу страницу, если вы делаете что-то подобное, так как это может перестать работать в любой день.

Если вы хотите сделать это так, как если бы он был синхронным, но все еще не блокировался, вам следует использовать async/await и, возможно, также некоторый ajax, основанный на обещаниях, таких как новый Fetch API.

Async function foo() { var res = await fetch(url) console.log(res.ok) var json = await res.json() console.log(json) }

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

если это ваш вариант использования, вы можете вместо этого взглянуть на navigator.sendBeacon

Страница также может отключить синхронизацию req либо с заголовками http, либо с атрибутом iframe allow

Я использовал ответ, данный Carcione, и изменил его, чтобы использовать JSON.

Function getUrlJsonSync(url){ var jqxhr = $.ajax({ type: "GET", url: url, dataType: "json", cache: false, async: false }); // "async" has to be "false" for this to work var response = {valid: jqxhr.statusText, data: jqxhr.responseJSON}; return response; } function testGetUrlJsonSync() { var reply = getUrlJsonSync("myurl"); if (reply.valid == "OK") { console.dir(reply.data); } else { alert("not valid"); } }

Я также получил статус с использованием свойства statusText возвращаемого объекта. Обратите внимание, что это статус ответа Ajax, а не действителен ли JSON.

Внутренний сервер должен вернуть ответ в правильном (правильно сформированном) JSON, иначе возвращаемый объект будет неопределенным.

При ответе на исходный вопрос необходимо учитывать два аспекта. Один говорит Ajax выполнять синхронно (путем установки async: false ), а другой возвращает ответ через оператор возврата функции вызова, а не в функцию обратного вызова.

Я также пробовал его с помощью POST, и он работал.

Function postUrlJsonSync(url, postdata){ var jqxhr = $.ajax({ type: "POST", url: url, data: postdata, dataType: "json", cache: false, async: false }); // "async" has to be "false" for this to work var response = {valid: jqxhr.statusText, data: jqxhr.responseJSON}; return response; }

Обратите внимание, что приведенный выше код работает только в случае, когда async является ложным . Если вы должны были установить async: true, возвращаемый объект jqxhr недействителен во время вызова AJAX, только позже, когда асинхронный вызов будет завершен, но слишком поздно установить переменную ответа .

С async: false вы получаете заблокированный браузер. Для неблокирующего синхронного решения вы можете использовать следующее:

ES6/ECMAScript2015

С ES6 вы можете использовать генератор и co library :

Beforecreate: function (node, targetNode, type, to) { co(function*(){ let result = yield jQuery.get("http://example.com/catalog/create/" + targetNode.id + "?name=" + encode(to.inp.value)); //Just use the result here }); }

ES7

С ES7 вы можете просто использовать asyc wait:

Beforecreate: function (node, targetNode, type, to) { (async function(){ let result = await jQuery.get("http://example.com/catalog/create/" + targetNode.id + "?name=" + encode(to.inp.value)); //Just use the result here })(); }

Во-первых, мы должны понимать, когда мы используем $.ajax и когда мы используем $.get/$. post

Когда мы требуем низкого уровня контроля над запросом ajax, таким как настройки заголовка запроса, настройки кеширования, синхронные настройки и т.д., тогда мы должны пойти на $.ajax.

$. get/$. post: Когда мы не требуем низкого уровня контроля над ajax-запросом. Просто просто получайте/отправляйте данные на сервер. Это сокращение

$.ajax({ url: url, data: data, success: success, dataType: dataType });

и, следовательно, мы не можем использовать другие функции (синхронизация, кеш и т.д.) с помощью $.get/$. post.

Следовательно, для управления низким уровнем (синхронизация, кеш и т.д.) по запросу ajax мы должны перейти на $.ajax

Синтаксис и описание:

Возвращаемое значение: Экземпляр объекта XHR (XMLHttpRequest).

Параметры:

    options – (объект) Объект в виде набора свойств (пар ключ:"значение"), которые задают параметры для Ajax запроса. Возможных параметров (свойств объекта options) очень много, и обычно в большинстве случаев они используются далеко не все, а только некоторые из них. К тому же, все эти параметры являются необязательными, т.к. значение любого из них может быть установлено по умолчанию с помощью метода $.ajaxSetup() .

    Для настройки Ajax-запроса доступны следующие свойства объекта options:

    • async – (boolean - логическое значение) По умолчанию имеет значение true, и тогда все запросы выполняются асинхронно (На то он и Ajax, чтобы операции выполнялись параллельно). Если установить зхначение false, что крайне нежелательно, то запрос будет выполняеться как синхронный (Другие действия браузера могут блокироваться на время, пока выполняется синхронный запрос. Да и вообще браузер может перестать реагировать и отвечать).

      beforeSend(XHR ) – (функция) Функция, вызываемая перед отправкой запроса. Она используетсядля установки дополнительных (пользовательских) заголовков или для выполнения других предварительных операций. В качестве единственного аргумента ей передается экземпляр объекта XHR (XMLHttpRequest). Если функция возвращает ложное значение (false), то происходит отмена запроса.

      cache – (boolean - логическое значение) Если имеет значение false, то запрашиваемые страницы не кэшируются браузером. (Браузер может выдавать результаты из кэша. Например, когда данные в ответе сервера на Ajax запрос всегда новые, то кеширование мешает). По умолчанию имеет значение true для типов данных text, xml, html, json. Для типов данных "script" и "jsonp" имеет значение по умолчанию false.

      complete(XHR, textStatus ) – (функция) Функция, вызываемая по окончании запроса независимо от его успеха или неудачи (а также после функций success и error, если они заданы). Функция получает два аргумента: экземпляр объекта XHR (XMLHttpRequest) и строку, сообщающую о состоянии "success" или "error" (в соответствии с кодом статуса в ответе на запрос).

      contentType – (строка) Тип содержимого в запросе (при передаче данных на сервер). По умолчанию имеет значение "application/x-www-form-urlencoded" (подходит для большинства случаев и используется по умолчанию также при отправке форм).

      context – (объект) Данный объект станет контекстом (this) для всех функций обратного вызова, связанных с данным Ajax-запросом (например, для функций success или error).

      $.ajax({ url: "test.html",
      context: document.body,
      success: function(){
      $(this).addClass("done");
      }});

      data – (строка | объект) Данные, отправляемые c запросом на сервер. Они преобразовываются в строку запроса и по умолчанию обязательно кодируются в URL-подобный вид (За автоматическое кодирование в формат URL отвечает параметр processData).

      Строка присоединяется к строке запроса URL, если запрос выполняется методом GET. Если же запрос выполняется методом POST, то данные передаются в теле запроса.

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

      Например, {Foo: [ "bar1", "bar2"]} станет "&Foo=bar1&Foo=bar2" .

      dataFilter(data, type ) – (функция) Функция, которая вызывается в случае успеха запроса и используется для обработки данных, полученных в ответе сервера на запрос. Она возвращает данные, обработанные в соответствии с параметром "dataType", и передает их функции success. Данные типа text и xml передаются без обработки сразу функции success через свойство responseText или responseHTML объекта XMLHttpRequest. Функция dataFilter получает два аргумента:

    • data - полученные данные (тело ответа сервера),
    • type - тип этих данных (параметр "dataType").
    • dataType – (строка) Строка, определяющая название типа даных, ожидаемых в ответе сервера. Если тип данных не задан, jQuery сама пытается его определить, ориентируясь на MIME-тип ответа сервера. Допустимые значения:"xml", "html", "script", "json", "jsonp", "text". (Это необходимо для того, чтобы определить метод обработки данных, полученных в ответе на запрос, функцией dataFilter перед тем, как они будут переданы функции обратного вызова success.)

      error(XHR, textStatus, errorThrown ) – (функция) Функция , которая вызывается при неудачном запросе (если код статуса в ответе сервера сообщает об ошибке). Функции передаются три аргумента:

    • XHR - экземпляр объекта XMLHttpRequest,
    • textStatus - строка, описывающая тип ошибки, которая произошла ("timeout", "error", "notmodified" или "parsererror"),
    • errorThrown - необязательный параметр – объект-исключение, если таковой имеется (возвращается экземпляром объекта XHR).
    • global – (boolean - логическое значение) По умолчанию имеет значение true (разрешен вызов глобальных обработчиков событий на различных этапах Ajax-запроса, например, функций ajaxStart или ajaxStop). Значение false устанавливается, чтобы предотвратить их срабатывание. (Используется для управления Ajax-событиями).

      ifModified – (boolean - логическое значение) Если установлено значение true, то запрос считается успешным только в том случае, если данные в ответе изменились с момента последнего запроса (jQuery определяет, совпадает ли компонент в кэше браузера с тем, что находится на сервере, путем проверки заголовка "Last-Modified" с датой последней модификации содержимого, а в jQuery 1.4 также проверяется заголовок "Etag" – строка с версией компонента). По умолчанию имеет значение false, т.е. успешность запроса не зависит от заголовков и от изменений в ответе.

      jsonp – (строка) Переопределяет имя функции обратного вызова для кроссдоменного запроса jsonp. Заменяет собой ключевое слово callback в части "callback=?" строки GET запроса (добавляемой к URL) или передаваемой в теле запроса при передаче методом POST. По умолчанию jQuery автоматически генерирует уникальное имя для функции обратного вызова.

      jsonpCallback – (строка) Определяет имя функции обратного вызова для jsonp-запроса. Это значение будет использоваться вместо случайного имени, автоматически генерируемого библиотекой jQuery. Использование данного параметра позволяет избегать пропусков кэширования браузером GET запросов. Желательно разрешать jQuery генерировать новое имя для каждого нового кроссдоменного запроса на сервер для удобства управления запросами и ответами.

      password – (строка) Пароль, который будет использоваться в ответ на требование HTTP авторизации на сервере.

      processData – (boolean - логическое значение) По умолчанию имеет значение true, и данные, передаваемые на сервер в параметре data, преобразовываются в строку запроса с типом содержимого "Application / X-WWW-форм-urlencoded" и кодируются. Если такая обработка нежелательна (когда необходимо отправить на сервер другие данные, например DOMDocument или объект xml), то ее можно обойти, установив для данного параметра значение false.

      scriptCharset – (строка) При выполнении запросов методом GET и запросов, ориентированных на получение данных типа "jsonp" или "script", указывает кодировку символов запроса (например "UTF-8" или "CP1251"). Полезно при различиях между кодировками на стороне клиента и на серверной стороне.

      success(data, textStatus, XHR ) – (функция) Функция, которая вызывается при успешном запросе (если код статуса в ответе на запрос сообщает об успехе). Функции передаются три аргумента:

    • data - данные, возвращаемые сервером в ответе, предварительно обработанные функцией dataFilter в соответствии со значением параметра dataType,
    • textStatus - строку с кодом статуса, сообщающем об успехе,
    • XHR - экземпляр объекта XMLHttpRequest.
    • timeout – (число) Устанавливает максимальное время ожидания ответа сервера в милисекундах. Имеет приоритет над глобальной установкой предельного времени ожидания через $.AjaxSetup. Если лимит времени ожидания превышен, то выполнение запроса прерывается и вызывается функция обработки ошибок error (если она установлена). Это можно использовать, например, для того, чтобы назначить определенному запросу более длительное время ожидания, чем время, установленное для всех запросов.

      traditional – (boolean - логическое значение) Необходимо установить значение true, чтобы использовать традиционную (упрощенную) сериализацию (преобразование) данных при отправке (без рекурсивного преобразования в URL-подобную строку объектов или массивов, которые вложены в другие массивы или объекты).

      type – (строка) HTTP-метод передачи данных при выполнении запроса. По умолчанию данные передаются методом GET. Обычно используются GET или POST. Также можно использовать методы PUT и DELETE, но это не рекомендуется, ввиду того, что они поддерживаются не всеми браузерами.

      url – (строка) Строка, содержащая URL-адрес, по которому посылается запрос. По умолчанию это текущая страница.

      username – (строка) Имя пользователя, которое будет использоваться для HTTP авторизации на сервере.

      xhr – (функция) Функция, вызываемая для создания экземпляра объекта XMLHttpRequest. По умолчанию создание объекта XHR реализовано через ActiveXObject в браузере IE, либо через встроенный объект типа XMLHttpRequest в остальных случаях.

  • // Выполнить асинхронный Ajax-запрос с помощью метода POST. // Отправить данные на сервер и в случае успеха вывести // ответ сервера в диалоговом окне. $.ajax({ type: "POST", url: "test.php", data: "name=John&location=Boston", success: function(msg){ alert("Data Saved: " + msg); } });




  • Что такое AJAX я думаю рассказывать не стоит, ибо с приходом веб-два-нуля большинство пользователей уже воротят носом от перезагрузок страниц целиком, а с появлением jQuery реализация упростилась в разы...

    Примечание : Во всех примерах используется сокращенный вариант вызова jQuery методов, используя функцию $ (знак доллара)

    Начнем с самого простого - загрузка HTML кода в необходимый нам DOM элемент на странице. Для этой цели нам подойдет метод load. Данный метод может принимать следующие параметры:

  • url запрашиваемой страницы
  • функция которой будет скормлен результат (необязательный параметр)
  • Приведу пример JavaScript кода:
    // по окончанию загрузки страницы
    $(document) . ready(function () {
    // вешаем на клик по элементу с id = example-1
    $("#example-1" ) . click(function () {
    // загрузку HTML кода из файла example.html
    $(this) . load("ajax/example.html" ) ;
    } )
    } ) ;
    Пример подгружаемых данных (содержимое файла example.html ):
    jQuery.ajax Это самый основной метод, а все последующие методы лишь обертки для метода jQuery.ajax. У данного метода лишь один входной параметр - объект включающий в себя все настройки (выделены параметры которые стоит запомнить):
    • async - асинхронность запроса, по умолчанию true
    • cache - вкл/выкл кэширование данных браузером, по умолчанию true
    • contentType - по умолчанию «application/x-www-form-urlencoded»
    • data - передаваемые данные - строка иль объект
    • dataFilter - фильтр для входных данных
    • dataType - тип данных возвращаемых в callback функцию (xml, html, script, json, text, _default)
    • global - тригер - отвечает за использование глобальных AJAX Event"ов, по умолчанию true
    • ifModified - тригер - проверяет были ли изменения в ответе сервера, дабы не слать еще запрос, по умолчанию false
    • jsonp - переустановить имя callback функции для работы с JSONP (по умолчанию генерируется на лету)
    • processData - по умолчанию отправляемые данный заворачиваются в объект, и отправляются как «application/x-www-form-urlencoded», если надо иначе - отключаем
    • scriptCharset - кодировочка - актуально для JSONP и подгрузки JavaScript"ов
    • timeout - время таймаут в миллисекундах
    • type - GET либо POST
    • url - url запрашиваемой страницы
    Локальные :
    • beforeSend - срабатывает перед отправкой запроса
    • error - если произошла ошибка
    • success - если ошибок не возникло
    • complete - срабатывает по окончанию запроса
    Для организации HTTP авторизации (О_о):
    • username - логин
    • password - пароль
    Пример javaScript"а:
    $.ajax ({
    url: "/ajax/example.html" , // указываем URL и
    dataType : "json" , // тип загружаемых данных
    success: function (data, textStatus) { // вешаем свой обработчик на функцию success
    $.each (data, function (i, val) { // обрабатываем полученные данные
    /* ... */
    } ) ;
    }
    } ) ; jQuery.get Загружает страницу, используя для передачи данных GET запрос. Может принимать следующие параметры:
  • url запрашиваемой страницы
  • передаваемые данные (необязательный параметр)
  • callback функция, которой будет скормлен результат (необязательный параметр)
  • тип данных возвращаемых в callback функцию (xml, html, script, json, text, _default)
  • Отправка Формы Для отправки формы посредством jQuery можно использовать любой из перечисленных способов, а вот для удобства «сбора» данных из формы лучше использовать плагин jQuery Form Отправка Файлов Для отправки файлов посредством jQuery можно использовать плагин Ajax File Upload иль One Click Upload Примеры использования JSONP Отдельно стоит отметить использование JSONP - ибо это один из способов осуществления кросс-доменной загрузки данных. Если немного утрировать - то это подключение удаленного JavaScript"a, содержащего необходимую нам информациию в формате JSON, а так же вызов нашей локальной функции, имя которой мы указываем при обращении к удаленному серверу (обычно это параметр callback ). Чуть более наглядно это можно продемонстрировать следующая диаграмма (кликабельно):


    При работе с jQuery имя callback функции генерируется автоматически для каждого обращения к удаленному серверу, для этого достаточно использовать GET запрос ввида:
    http://api.domain.com/?type=jsonp&query=test&callback=?
    Вместо последнего знака вопроса (?) будет подставлено имя callback функции. Если же Вы не хотите использовать данный способ, то Вам необходимо будет явно указать имя callback функции, используя опцию jsonp при вызове метода jQuery.ajax().

    Сегодня, асинхронные запросы, они же ajax с одноименной функцией в jQuery, используются чуть ли не на каждом сайте. Ведь, сама идея частичного изменения контента на странице обладает массой плюсов. Это и скорость, и объемы трафика, и удобство, и динамичность страниц. Однако, существует одна маленькая хитрость, внимание на которую редко где обращают. Хотя, со временем именно с ней в том или ином виде встречается каждый. Речь идет об организации очереди асинхронных запросов или троттлинге.

    Зачем это нужно? - можете спросить вы. Все очень просто. Несмотря на то, что ajax обладает массой преимуществ, нельзя упускать из виду, что запрос к серверу остается запросом к серверу, со всем вытекающим отсюда.

    Например, представьте себе следующую ситуацию. У вас есть обычный сайт на php, это может быть и другой язык - не особенно важно. Каждый запрос к серверу требует от него минимально выделить оперативную память на обработку запроса. Допустим, это будет 20 Мб. Загрузка же полной страницы сложного приложения потребует, к примеру, 50 Мб. Разбивая страницу на то, что стоит загружать пользователям сразу, а что стоит загружать асинхронно, вы можете создать ситуацию, когда ваше асинхронное приложение будет требовательнее и тяжелее того же приложения, но с классическим подходом. К примеру, вместо одного запроса на 50 Мб, вы можете создать, пусть даже и оптимизированных, десяток другой 20 Мб запросов в дополнение к первому запросу, которые суммарно будут существенно сильнее загружать сервер.

    Кроме того, необходимо понимать, что запросы к серверу отличаются от запросов к статическим файлам и ресурсам. Если брать приведенный пример, то вместо одного запроса, у вас получился десяток другой, каждый из которых будет проходить все этапы обработки, включая проверки безопасности, загрузку всех необходимых классов и многое другое. Что, чаще всего, будет практически равноценно открытию обычных страниц для каждого из асинхронных запросов (помните, что многие статические ресурсы кэшируются браузерами не загружаются повторно). Другими словами, вместо 1 тяжелой страницы, вы будете заставлять сервер открывать 1 тяжелую и десяток другой простых. Поэтому, очень важно следить за тем, что бы асинхронность в приложении действительно давала положительные результаты, а не наоборот приводила к ухудшению производительности.

    Одним из способов как-то побороть проблему является разнесение всех асинхронных запросов по времени. И рамках данной статьи будет показано, как можно организовать очередь асинхронных запросов на jQuery и снизить вероятность перегрузки сервера.

    Примечание : В одной из предыдущих статей уже рассказывался вариант организации поэтапной асинхронной загрузки данных на jQuery , но данный способ подойдет далеко не для всех ситуаций.

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

    И первым делом подкорректируем страницу index.html, оставив только несколько типовых функций, и слегка изменим структуру таблиц следующим образом:

    function clearTable() { $(".table-loader td").html(""); } function setLoaderImgs(selector) { $(selector + " .table-loader td").html(""); } function getFakeLoader(startDate, selector, func) { return function () { func("data.json?callback=?", { contentType: "text/plain; charset=utf-8", dataType: "jsonp", jsonpCallback: function (result) { // Пишем время загрузки $(selector).html("Время от начала: " + ((+new Date() - startDate)/1000.0).toFixed(2) + " секунд"); } }); }; } function formTestFor(selector, func) { $(selector + " .start-process").click(function () { }); } $(function () { formTestFor(".left-table"); formTestFor(".right-table"); }); Очередь асинхронных запросов на jQuery (ajax) или троттлинг Простой подход к загрузке Начать загрузку

    Более гибкий подход к загрузке Начать загрузку

    Заметьте, что функция getFakeLoader была немного переделана, чтобы для ajax-запросов вместо привычного вида функции $.ajax (jQuery.ajax) вызывалась функция из параметра.

    Теперь можно приступать к самим способам.

    Организация простой очереди асинхронных запросов на 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 запрос, а сразу несколько.

    Идея пакетной очередь ajax-запросов на jQuery с распределением по времени очень проста и совмещает в себе решение проблем предыдущего подхода. Суть заключается в следующем. Вы создаете специальный счетчик, который ограничивает количество разрешенных асинхронных запросов в интервале времени. И если этот счетчик превышается, то запрос откладывается до следующего интервала времени. Такой подход позволяет, во-первых, не ограничиваться интервалом ожидания (не ждать время пока запустится циклическая функция для запуска запроса), а во-вторых, уменьшить время простоя для запуска первых ajax-запросов. И вот код:

    // Пакетная очередь аjax-запросов на jQuery с распределением по времени $.qajax = function (url, options) { // Параметр в миллисекундах, когда необходимо запускать следующий ajax запрос var intervalTimeout = 550; // Количество разрешенных запросов в интервале времени. var countAjax = 5; // Определяем переменную для хранения очереди $._qajaxQueue = $._qajaxQueue || ; // Количество использованных запросов $._qajaxUsed = ($._qajaxUsed || 0) + 0; // Сохраняем параметры запроса $._qajaxQueue.push({ url: url, options: options }); // Если еще можно запускать запросы в интервале while ($._qajaxUsed < countAjax && $._qajaxQueue.length > 0) { // Получаем первый запрос var params = $._qajaxQueue.shift(); // Если данные в запросе хранились, то запускаем ajax-запрос if(params) { $.ajax(params.url, params.options); } // Увеличиваем счетчик $._qajaxUsed++; } // Определяем циклический запуск асинхронного запроса по времени // Или если функция уже определена, то созерцаем красоту присваивания переменной самой себе $._qajaxInterval = $._qajaxInterval || setInterval(function () { // Обнуляем счетчик использованных запросов $._qajaxUsed = 0; // Пробегаемся по сохраненным ранее запросам и запускаем первые countAjax запросов while ($._qajaxUsed < countAjax && $._qajaxQueue.length > 0) { // Получаем первый запрос var params = $._qajaxQueue.shift(); // Если данные в запросе хранились, то запускаем ajax-запрос if(params) { $.ajax(params.url, params.options); } // Увеличиваем счетчик $._qajaxUsed++; } }, intervalTimeout); };

    Так же подкорректируем обработчик события загрузки DOM:

    $(function () { formTestFor(".left-table", $.qajaxSimple); formTestFor(".right-table", $.qajax); });

    Теперь, нажав на кнопку запуска процесса из правой таблицы, вы должны увидеть примерно следующее:

    Примечание : Интервал составлял 550 мс, количество разрешенных запросов 5.

    Как можно увидеть, теперь, запустив одновременно 8 асинхронных запросов, они будут распределены во времени. Первые 5 запросов будут выполнены в то же время, как они были запущены, а оставшиеся 3 будут вызваны после 550 мс. Такой подход позволил сократить нагрузку и уменьшить общее ожидание.

    Плюсов и возможностей использования данного метода достаточно много. Во-первых, вы можете ограничить действия пользователей. К примеру, существуют люди, которые не дожидаются окончательной загрузки страницы и начинают усиленно пытаться запускать другие асинхронные запросы (щелкать по куче кнопок, другими словами, нажимать все подряд), тем самым загружая ваш сервер донельзя. Во-вторых, при корректных настройках (подбираются в зависимости от проекта), обычный пользователь даже не узнает, что у вас есть какие-либо ограничения по количеству запросов. В-третьих, очередь по-прежнему будет позволять разгружать ваш сервер, за счет разнесения запросов во времени. В-четвертых, искусственная задержка будет сказываться не на всех запросах. И многие другие.

    Мы познакомились с прямыми методами jQuery для работы с Ajax (такими как get(), post() и load()). В этой статье описан низкоуровневый программный интерфейс jQuery Ajax API .

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

    Простые Ajax-запросы

    Создавать запросы с помощью низкоуровневого API не намного сложнее, чем с помощью прямых или вспомогательных методов. Разница состоит в том, что такой подход позволяет контролировать многие другие аспекты запроса и получать о выполняющемся запросе гораздо больше информации. Центральное место в низкоуровневом API занимает метод ajax() , простой пример использования которого приведен ниже (здесь используется исходный файл и файл mydata.json, описанные в предыдущей статье):

    $(function() { $.ajax("mydata.json", { success: function(data) { var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); } }); });

    Аргументами метода ajax() являются запрашиваемый URL и объект отображения данных, свойства которого определяют набор пар "ключ-значение", каждая из которых определяет некий параметр запроса. Здесь передаваемый методу ajax() объект содержит только один параметр, success, задающий функцию, которая будет вызываться в случае успешного выполнения запроса.

    В данном примере мы запрашиваем у сервера файл mydata.json и используем его вместе с шаблоном данных для создания элементов и вставки их в документ, как это делалось в предыдущей статье с помощью прямых методов. По умолчанию метод ajax() создает HTTP-запрос GET, т.е. данный пример эквивалентен использованию методов get() и getJSON().

    Объект jqXHR

    Метод ajax() возвращает объект jqXHR, который можно использовать для получения подробной информации о запросе и с которым можно взаимодействовать. Объект jqXHR представляет собой оболочку объекта XMLHttpRequest , составляющую фундамент браузерной поддержки Ajax.

    При выполнении большинства операций Ajax объект jqXHR можно просто игнорировать, что я и рекомендую делать. Этот объект используется в тех случаях, когда необходимо получить более полную информацию об ответе сервера, чем та, которую удается получить иными способами. Кроме того, его можно использовать для настройки параметров Ajax-запроса, но это проще сделать, используя настройки, доступные для метода ajax(). Свойства и методы объекта jqXHR описаны в таблице ниже:

    Свойства и методы объекта jqXHR Свойство/метод Описание
    readyState Возвращает индикатор хода выполнения запроса на протяжении всего его жизненного цикла, принимающий значения от 0 (запрос не отправлен) до 4 (запрос завершен)
    status Возвращает код состояния HTTP, отправленный сервером
    statusText Возвращает текстовое описание кода состояния
    responseXML Возвращает ответ в виде XML (если он является XML-документом)
    responseText Возвращает ответ в виде строки
    setRequest(имя, значение) Возвращает заголовок запроса (это можно сделать проще с помощью параметра headers)
    getAllResponseHeaders() Возвращает в виде строки все заголовки, содержащиеся в ответе
    getResponseHeaders(имя) Возвращает значение указанного заголовка ответа
    abort() Прерывает запрос

    Объект jqXHR встречается в нескольких местах кода. Сначала он используется для сохранения результата, возвращаемого методом ajax(), как показано в примере ниже:

    $(function() { var jqxhr = $.ajax("mydata.json", { success: function(data) { var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); } }); var timerID = setInterval(function() { console.log("Статус: " + jqxhr.status + " " + jqxhr.statusText); if (jqxhr.readyState == 4) { console.log("Запрос выполнен: " + jqxhr.responseText); clearInterval(timerID); } }, 100); });

    В этом примере мы сохраняем результат, возвращаемый методом ajax(), а затем используем метод setInterval() для вывода информации о запросе каждые 100 мс. Использование результата, возвращаемого методом ajax(), не изменяет того факта, что запрос выполняется асинхронно, поэтому при работе с объектом jqXHR необходимо соблюдать меры предосторожности. Для проверки состояния запроса мы используем свойство readyState (завершению запроса соответствует значение 4) и выводим ответ сервера на консоль.

    Для данного сценария консольный вывод выглядит так (в вашем браузере он может выглядеть несколько иначе):

    Я использую объект jqXHR лишь в редких случаях и не делаю этого вообще, если он представляет собой результат, возвращаемый методом ajax(). Библиотека jQuery автоматически запускает Ajax-запрос при вызове метода ajax(), и поэтому я не считаю возможность настройки параметров запроса сколько-нибудь полезной. Если я хочу работать с объектом jqXHR (как правило, для получения дополнительной информации об ответе сервера), то обычно делаю это через параметры обработчика событий, о которых мы поговорим далее. Они предоставляют мне информацию о состоянии запроса, что избавляет от необходимости выяснять его.

    Задание URL-адреса запроса

    Одним из наиболее важных доступных параметров является параметр url , позволяющий указать URL-адрес для запроса. Можно использовать этот параметр как альтернативу передаче URL-адреса в качестве аргумента метода ajax(), как показано в примере ниже:

    $(function() { $.ajax({ url: "mydata.json", success: function(data) { var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); } }); });

    Создание POST-запроса

    Для задания требуемого типа запроса, который необходимо выполнить, используется параметр type . По умолчанию выполняются GET-запросы, как в предыдущем примере. Пример использования метода ajax() для создания POST-запроса и отправки данных формы на сервер приведен ниже:

    $(function() { $.ajax({ url: "mydata.json", success: function(data) { var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); } }); // Обработчик клика по кнопке "Заказать" $("button").click(function(e) { $.ajax({ url: "phphandler.php", type: "post", data: $("form").serialize(), success: processServerResponse, dataType: "json" }); e.preventDefault() }); function processServerResponse(data) { // Изначально скрываем всю продукцию var inputElems = $("div.dcell").hide(); for (var prop in data) { // Отображаем только ту продукцию, заказ которой больше 0 // (в ответе от сервера содержится только такая продукция) var filtered = inputElems.has("input") .appendTo("#row1").show(); } // Скрываем базовые элементы формы $("#buttonDiv, #totalDiv").remove(); // Отображаем новые элементы из шаблона totalTmpl $("#totalTmpl").tmpl(data).appendTo("body"); } }); Всего заказов: ${total} Заказать .png"/> ${name}:

    Здесь я не буду подробно описывать этот пример, т.к. мы его рассмотрели подробно в предыдущей статье (только с использованием метода post()). Отмечу только, что здесь дополнительно к type мы использовали еще несколько параметров. Для указания цели POST-запроса используется описанный ранее параметр url. Пересылаемые данные указываются с помощью параметра data, значение которого устанавливается с помощью метода serialize(), описанного в предыдущей статье. Тип данных, получаемых от сервера указывается в параметре dataType.

    Работа с событиями Ajax

    Несколько параметров позволяют указывать функции для обработки событий, которые могут запускаться на протяжении жизненного цикла Ajax-запроса. Именно таким способом вы будете указывать функции обратного вызова, играющие столь важную роль в Ajax-запросах. С одной из них вы уже познакомились при рассмотрении параметра success в предыдущем примере. Список параметров, связанных с событиями, вместе с их краткими описаниями приведен в таблице ниже:

    Обработка успешных запросов

    В примерах выше, при использовании параметра success, в вызове функции были опущены два аргумента - сообщение, описывающее результат запроса, и объект jqXHR. Пример использования функции, которая принимает эти аргументы, приведен ниже:

    $(function() { $.ajax({ url: "mydata.json", success: function(data, status, jqxhr ) { console.log("Статус: " + status); console.log("jqXHR статус: " + jqxhr.status + " " + jqxhr.statusText); console.log(jqxhr.getAllResponseHeaders()); var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); } }); });

    Аргумент status - это строка, описывающая исход запроса. Функция обратного вызова, которую мы задаем, используя параметр success, выполняется лишь для успешных запросов, и поэтому значением данного аргумента обычно является success. Исключением является случай, когда вы используете параметр ifModified, описанный далее.

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

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

    В данном случае результат имеет следующий вид (в зависимости от того, какой сервер вы используете, у вас может быть другой набор заголовков):

    Обработка ошибок

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

    Error {color: red; border: medium solid red; padding: 4px; margin: auto; width: 200px; text-align: center}

    $(function() { $.ajax({ url: "NoSuchFile.json", success: function(data) { var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); }, error: function(jqxhr, status, errorMsg) { $("") .text("Статус: " + status + " Ошибка: " + errorMsg) .insertAfter("h1"); } }); });

    Здесь запрашивается отсутствующий на сервере файл NoSuchFile.json, и поэтому запрос заведомо не сможет быть выполнен, в результате чего будет вызвана функция, заданная с помощью параметра error. Аргументами этой функции являются объект jqXHR, а также сообщение о состоянии ошибки и сообщение об ошибке, полученное в ответе сервера. Внутри этой функции в документ добавляется элемент div, отображающий значения аргументов status и errorMsg, как показано на рисунке:

    Настройка параметров запросов перед их отправкой

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

    $(function() { $.ajax({ success: function(data) { var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); }, error: function(jqxhr, status, errorMsg) { $("") .text("Статус: " + status + " Ошибка: " + errorMsg) .insertAfter("h1"); }, beforeSend: function(jqxhr, settings) { settings.url = "mydata.json"; } }); });

    Аргументами указанной функции являются объект jqXHR (который может пригодиться для настройки заголовков запроса или отмены запроса, прежде чем он будет отправлен) и объект, содержащий параметры, переданные методу ajax(). В данном примере URL-адрес для Ajax-запроса задается с помощью параметра beforeSend.

    Задание нескольких обработчиков событий

    В предыдущих примерах мы реагировали на наступление событий, связанных с Ajax-запросами, вызовом одной функции, но в параметрах success, error, complete и beforeSend можно задавать массив функций, каждая из которых будет выполняться при запуске соответствующего события. Простой пример этого приведен ниже:

    $(function() { $.ajax({ success: , beforeSend: function(jqxhr, settings) { settings.url = "mydata.json"; } }); function processData(data, status, jqxhr) { var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); } function reportStatus(data, status, jqxhr) { console.log("Статус: " + status + " Код результата: " + jqxhr.status); } });

    В этом примере для параметра success задан массив, состоящий из двух функций, одна из которых использует данные для добавления элементов в документ, а вторая выводит информацию на консоль.

    Настройка контекста для событий

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

    $(function() { $.ajax({ success: function(data) { var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); }, beforeSend: function(jqxhr, settings) { settings.url = "mydata.json"; }, context: $("h1"), complete: function(jqxhr, status) { var color = status == "success" ? "green" : "red"; this.css("border", "thick solid " + color); } }); });

    Здесь параметр context устанавливается на объект jQuery, содержащий элементы h1 документа. В функции, определяемой параметром complete, мы выделяем рамкой выбранные элементы (в данном случае - элемент, поскольку в документе есть только один элемент h1) путем вызова метода css() для объекта jQuery (на который ссылаемся через this). Цвет рамки определяется на основании состояния запроса.

    С помощью параметра context можно установить в качестве контекста любой объект, и ответственность за выполнение только допустимых для этого объекта операций лежит на вас. Например, если вы задаете в качестве контекста элемент HTMLElement, то до того, как вызывать для него какие-либо методы jQuery, вы должны передать этот объект функции $().

    Настройка базовых параметров Ajax-запросов

    Существует группа параметров, с помощью которых можно выполнить базовую настройку Ajax-запроса (некоторые из них, url и type, мы рассмотрели выше). Из всех доступных параметров они представляют наименьший интерес, и их имена в основном говорят сами за себя. Параметры, о которых идет речь, приведены в таблице ниже:

    Базовые конфигурационные параметры Ajax-запроса Параметр Описание
    accepts Устанавливает для запроса значение заголовка Accept, который указывает MIME-типы, поддерживаемые браузером. По умолчанию это значение определяется параметром dataType
    cache Значение false указывает на то, что содержимое запроса не должно кэшироваться сервером. По умолчанию кешируются все типы данных, кроме script и jsonp
    contentType Устанавливает для запроса значение заголовка content-туре
    dataType Указывает, какие типы данных ожидаются от сервера. Если используется этот параметр, то jQuery будет игнорировать информацию, предоставляемую сервером о типе запроса
    headers Задает дополнительные заголовки и значения, которые должны включаться в запрос
    jsonp Задает строку, которую следует использовать вместо функции обратного вызова при выполнении запросов JSONP (кроссдоменные запросы). Этот параметр требует согласования с сервером
    jsonpCallback Задает имя функции обратного вызова, которое должно использоваться вместо автоматически сгенерированного случайного имени, используемого jQuery по умолчанию
    password Задает пароль, который должен использоваться в запросе при прохождении процедуры аутентификации
    scriptCharset Указывает jQuery, какой набор символов используется при кодировании запрашиваемого JavaScript-содержимого
    timeout Задает длительность тайм-аута (в миллисекундах) для запроса
    userName Задает имя пользователя, которое должно использоваться в запросе при прохождении процедуры аутентификации
    Задание тайм-аутов и заголовков

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

    $(function() { $.ajax({ timeout: 5000, headers: { "X-HTTP-Method-Override": "PUT" }, success: function(data) { var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); }, error: function(jqxhr, status, errorMsg) { console.log("Error: " + status); } }); });

    В этом примере параметр timeout устанавливает максимальную длительность тайм-аута, равную 5 сек. Если запрос за это время не будет выполнен, то вызовется функция, заданная с помощью параметра error, и будет выведен код ошибки, определяемый параметром status.

    Таймер запускается сразу же после передачи запроса браузеру, и большинство браузеров налагают ограничения на количество одновременно выполняющихся запросов. Это означает, что существует риск того, что к моменту истечения тайм-аута запрос даже не будет запущен. Чтобы избежать этого, необходимо располагать сведениями об ограничениях браузера, а также об объеме и ожидаемой длительности любых других выполняющихся Ajax-запросов.

    Дополнительно в этом примере ниже используется параметр headers, с помощью которого в запрос добавляется заголовок. Для указания заголовков используется объект отображения данных. Используемый здесь заголовок может быть полезным для создания веб-приложений, поддерживающих архитектурный стиль REST, если только сервер правильно его распознает.

    Использование дополнительных конфигурационных параметров

    В следующих разделах описаны наиболее полезные и заслуживающие внимания дополнительные параметры, применимые к Ajax-запросам. Обычно они редко используются, но в случаях, когда в них возникает потребность, они оказываются незаменимыми. Эти параметры позволяют осуществлять точную настройку взаимодействия jQuery с Ajax.

    Создание синхронных запросов

    Управление режимом выполнения запросов осуществляется с помощью параметра async . Значение true, используемое для этого параметра по умолчанию, означает, что запрос будет выполняться в асинхронном режиме, тогда как значению false соответствует синхронный режим.

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

    Игнорирование данных, оставшихся неизменными

    С помощью параметра ifModified можно обеспечить получение данных лишь в том случае, если с момента последнего запроса они были изменены. Такое поведение определяется заголовком Last-Modified. Благодаря этому удается избежать бесполезной пересылки данных, которая не даст пользователю никакой новой информации по сравнению с той, которой он уже располагает. По умолчанию параметр ifModified имеет значение false, указывающее jQuery на необходимость игнорирования заголовка Last-Modified и предоставления данных в любом случае.

    Пример использования этого параметра приведен ниже:

    $(function() { $("button").click(function(e) { $.ajax("mydata.json", { ifModified: true, success: function(data, status) { if (status == "success") { $("#row1, #row2").children().remove(); var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); } else if (status == "notmodified") { $("img").css("border", "thick solid green"); } } }); e.preventDefault(); }) });

    В этом примере значение параметра ifModified устанавливается равным true. Функция success вызывается всегда, но если с того момента, когда содержимое запрашивалось в последний раз, оно не изменилось, то аргумент data будет иметь значение undefined, а аргумент status - значение notmodified .

    В данном случае выполняемые действия определяются значением аргумента status. Если значением этого аргумента является success, то аргумент data используется для добавления элементов в документ. Если же аргумент status имеет значение notmodified, то мы используем метод css() для выделения рамкой элементов, которые уже имеются в документе.

    В ответ на событие click, связанное с кнопкой, вызывается метод ajax(). Это дает возможность многократно повторять один и тот же запрос, чтобы продемонстрировать влияние параметра ifModified, как показано на рисунке:

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

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

    Обработка кода ответа

    Параметр statusCode позволяет выбирать варианты дальнейших действий в зависимости от кода ответов на HTTP-запросы. Его можно использовать либо вместо параметров success и error, либо в дополнение к ним. Пример самостоятельного использования параметра statusCode приведен ниже:

    $(function() { $.ajax({ url: "mydata.json", statusCode: { 200: function(data) { var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); }, 404: function(jqxhr, status, errorMsg) { $("") .text("Статус: " + status + " Ошибка: " + errorMsg) .insertAfter("h1"); } } }); });

    Здесь параметр statusCode задан в виде объекта, устанавливающего связь между кодами ответов на HTTP-запросы и соответствующими им функциями, которые должны быть выполнены на сервере. Какие именно аргументы передаются функциям, зависит от того, отражает ли код ответа успешное выполнение запроса или ошибку.

    Если код (например, 200) соответствует успешному запросу, то аргументы совпадают с теми, которые передавались бы функции, определяемой параметром success. В противном случае (например, при коде ответа 404, означающем, что запрашиваемый файл не найден) аргументы совпадают с теми, которые передавались бы функции, определяемой параметром error.

    Как видите, это средство не дает непосредственной информации о кодах ответа. Я часто пользуюсь им в процессе отладки взаимодействия браузера с сервером, обычно для того, чтобы выяснить, почему jQuery ведет себя не так, как мне хотелось бы. При этом я использую параметр statusCode в дополнение к параметрам success и error и вывожу информацию на консоль. Если эти параметры используются совместно, то сначала будут выполнены функции success и error, а затем уже - функции, определяемые параметром statusCode.

    Предварительная очистка ответных данных

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

    Это средство мне очень помогает при работе с серверами Microsoft ASP.NET, присоединяющими лишние данные к данным JSON. Удаление таких данных с помощью параметра dataFilter требует лишь минимальных усилий. Пример использования параметра dataFilter приведен ниже:

    $(function() { $.ajax({ url: "mydata.json", success: function(data) { var template = $("#flowerTmpl"); template.tmpl(data.slice(0, 3)).appendTo("#row1"); template.tmpl(data.slice(3)).appendTo("#row2"); }, dataType: "json", dataFilter: function(data, dataType) { if (dataType == "json") { var filteredData = $.parseJSON(data); filteredData.shift(); return JSON.stringify(filteredData.reverse()); } else { return data; } } }); });

    Функции передаются данные, полученные с сервера, и значение параметра dataType. Если параметр dataType не используется, то второму аргументу присваивается значение undefined. Ваша задача заключается в том, чтобы вернуть отфильтрованные данные. В этом примере предмет нашего внимания - данные в формате JSON:

    Var filteredData = $.parseJSON(data); filteredData.shift(); return JSON.stringify(filteredData.reverse()); ...

    Для повышения иллюстративности примера в нем выполняются некоторые дополнительные операции. Во-первых, данные JSON преобразуются в массив JavaScript с помощью метода jQuery parseJSON. Затем из массива удаляется первый элемент с помощью метода shift(), а порядок следования остальных его элементов обращается с помощью метода reverse().

    Все, что требуется от функции, - вернуть строку, и поэтому мы вызываем метод JSON.stringify(), зная, что jQuery преобразует данные в объект JavaScript, прежде чем вызвать функцию success. В данном примере была продемонстрирована возможность удаления элемента из массива, однако, в зависимости от ситуации, мы могли бы выполнить любой другой вид обработки.

    Конечный результат представлен на рисунке:

    Управление преобразованием данных

    Рассмотрение одной из самых любимых своих настроек я приберег напоследок. Должно быть, вы обратили внимание, что при получении определенных типов данных jQuery автоматически выполняет некоторые удобные преобразования. Например, получая данные JSON, jQuery предоставляет функцию success, использующую объект JavaScript, а не исходную необработанную строку JSON.

    Для управления подобными преобразованиями используется параметр converters . Значением этого параметра является объект, устанавливающий соответствие между типами данных и функциями, используемыми для их обработки. В примере ниже показано, как использовать этот параметр для автоматического преобразования HTML-данных в объект jQuery:

    $(function() { $.ajax({ url: "flowers.html", // В этом примере мы загружаем HTML-разметку, а не данные в формате JSON success: function(data, status, jqxhr) { var elems = data.filter("div").addClass("dcell"); elems.slice(0, 3).appendTo("#row1"); elems.slice(3).appendTo("#row2"); }, converters: { "text html": function(data) { return $(data); } } }); });

    В этом примере регистрируется функция для типа данных text html. Обратите внимание на пробел между компонентами указываемого MIME-типа (в отличие от формы записи text/html). Функция принимает данные, полученные от сервера, и возвращает преобразованные данные. В этом случае преобразование данных заключается в передаче HTML-фрагмента, содержащегося в файле flowers.html, функции $() и возврате результата. Отсюда следует, что к объекту, передаваемому в качестве аргумента data функции success, применимы обычные методы jQuery.

    Работая с преобразователями данных, можно слишком увлечься. Я всегда стараюсь избегать соблазна делать с помощью этих функций больше, чем следует. Например, иногда меня так и тянет применить к данным JSON шаблон и передать обратно полученные в результате HTML-элементы. И хотя этот прием очень удобен, он сослужит плохую службу, если кто-то другой будет пытаться расширить ваш код или, например, вам самому впоследствии потребуется организовать интенсивную обработку данных для получения их в исходной форме.

    Настройка и фильтрация Ajax-запросов

    После того как вы познакомились с методом ajax() и доступными для работы с ним параметрами, мы можем рассмотреть несколько дополнительных методов, предоставляемых jQuery для упрощения настройки запросов.

    Определение параметров, используемых по умолчанию

    Метод ajaxSetup() позволяет установить значения параметров, которые будут применяться по умолчанию во всех Ajax-запросах, тем самым освобождая вас от необходимости настраивать параметры при каждом запросе. Пример использования этого метода приведен ниже:

    ") .text("Статус: " + status + " Ошибка: " + errorMsg) .insertAfter("h1"); }, converters: { "text html": function(data) { return $(data); } } }); $.ajax({ url: "flowers.html", success: function(data, status, jqxhr) { var elems = data.filter("div").addClass("dcell"); elems.slice(0, 3).appendTo("#row1"); elems.slice(3).appendTo("#row2"); } }); });

    Метод ajaxSetup() вызывается с помощью функции jQuery $ аналогично тому, как это делалось в случае вызова метода ajax(). Аргументом метода ajaxSetup() является объект, содержащий значения параметров, которые вы хотите использовать по умолчанию для всех Ajax-запросов. В этом примере мы устанавливаем значения по умолчанию для параметров timeout, global, error и converters.

    После того как был вызван метод ajaxSetup(), нам остается определить значения лишь те значения параметров, которые мы хотим изменить, или те, которые не предоставляются по умолчанию. Это обеспечивает значительную экономию времени в тех случаях, когда приходится делать множество запросов с одинаковыми значениями параметров.

    Фильтрация запросов

    Метод ajaxSetup() определяет базовые значения конфигурационных параметров, применимые ко всем запросам Ajax. Возможности динамической настройки параметров для отдельных Ajax-запросов обеспечиваются методом ajaxPrefilter() . Пример использования этого метода приведен ниже:

    $(function() { $.ajaxSetup({ timeout: 15000, global: false, error: function(jqxhr, status, errorMsg) { $("") .text("Статус: " + status + " Ошибка: " + errorMsg) .insertAfter("h1"); }, converters: { "text html": function(data) { return $(data); } } }); $.ajaxPrefilter("json html", function(settings, originalSettings, jqxhr) { if (originalSettings.dataType == "html") { settings.timeout = 2000; } else { jqxhr.abort(); } }) $.ajax({ url: "flowers.html", dataType: "html", success: function(data, status, jqxhr) { var elems = data.filter("div").addClass("dcell"); elems.slice(0, 3).appendTo("#row1"); elems.slice(3).appendTo("#row2"); } }); });

    Указанная вами функция будет выполняться для каждого нового Ajax-запроса. Аргументами, передаваемыми функции, являются параметры запроса (включая любые значения по умолчанию, установленные вами с помощью метода ajaxSetup()), а также исходные параметры, переданные методу ajax() (исключая любые значения по умолчанию) и объекту jqXHR запроса.

    Мы вносим изменения в объект, передаваемый в качестве первого аргумента, как показано в примере. В данном сценарии, если среди параметров, передаваемых методу ajax(), присутствует параметр dataType, то длительность тайм-аута устанавливается равной двум секундам. Чтобы предотвратить отправку всех остальных запросов, для объекта jqXHR вызывается метод abort().

    Есть вопросы?

    Сообщить об опечатке

    Текст, который будет отправлен нашим редакторам: