Основы AJAX: Передача данных с помощью XMLHttpRequest
Сентябрь 8, 2007 – 19:43Здесь и далее, используя термин AJAX, мы будем иметь в виду не дословную расшифровку этой аббревиатуры (Asynchronous JavaScript and XML), а скорее обобщенную концепцию обмена данными между браузером клиента и веб-сервером без перезагрузки страницы. Для нас AJAX безусловно подразумевает JavaScript, но совсем не обязательно включает XML.
В данном цикле статей мы рассматриваем три базовых функциональных элемента, на которых основано большинство AJAX-приложений:
- передача данных с помощью XMLHttpRequest
- передача данных с помощью IFRAME
- передача данных с помощью элементов <script>
Передача данных с помощью XMLHttpRequest
Данный метод передачи данных прост и элегантен, а также совместим со всеми распространенными браузерами, в связи с чем закрывает подавляющее большинство потребностей обмена.
Начинается все с создания объекта XMLHttpRequest (данный код в большей части позаимствован отсюда):
function createXMLHttpRequest() {
var xmlReq = false;
// branch for native XMLHttpRequest object
if(window.XMLHttpRequest) {
try {
xmlReq = new XMLHttpRequest();
} catch(e) {
xmlReq = false;
}
// branch for IE/Windows ActiveX version
} else if(window.ActiveXObject) {
try {
xmlReq = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try {
xmlReq = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
xmlReq = false;
}
}
}
return xmlReq;
}
Мы будем вызывать эту функцию каждый раз, когда нам нужно будет получить экземпляр данного объекта. Несколько экземпляров XMLHttpRequest могут использоваться одновременно для отправки/получения данных от разных компонент на одной веб-странице.
Мы также используем эту функцию для определения AJAX-совместимости браузера клиента:
var userAgent = { };
userAgent.isAJAX = (createXMLHttpRequest()?true:false);
userAgent.isMozilla = (navigator.userAgent.match(/\bGecko\b/));
userAgent.isOpera = (navigator.userAgent.match(/\bOpera\b/));
userAgent.isInternetExplorer =
(navigator.userAgent.match(/\bMSIE\b/) && !userAgent.isOpera);
Для обмена данными с сервером мы используем следующий метод:
function callServer(method, url, data, dataType, func, arg) {
if (!method) method='GET';
var xmlReq = createXMLHttpRequest();
if(xmlReq) {
xmlReq.onreadystatechange = function() {
// only if xmlReq shows "loaded"
if (xmlReq.readyState == 4) {
func(arg, xmlReq.responseText, xmlReq.responseXML,
xmlReq.status, xmlReq.statusText);
}
};
xmlReq.open(method, url, true);
if (data) {
if (!dataType) dataType='application/xml';
if (typeof(data)!="string" && dataType.indexOf("charset=")<0
&& userAgent.isMozilla) dataType=dataType+';charset=utf-8';
// in Mozilla XML always serialized as UTF-8
xmlReq.setRequestHeader('Content-Type', dataType);
}
xmlReq.send(data);
return false;
}
return true;
}
Параметры вызова:
- method - HTTP-метод: ‘GET’, ‘POST’, … (не все браузеры поддерживают методы, отличные от GET/POST)
- url - адрес страницы (должен быть на том же домене, что и страница, с которой идет вызов функции - это ограничение безопасности присутствует во всех основных браузерах)
- data - данные для POST-запроса (тип данных нужно указать в параметре dataType)
- dataType - MIME-тип данных POST-запроса (полезные варианты: ‘application/xml’, ‘application/x-www-form-urlencoded’)
- func - функция, которая будет вызвана автоматически по завершении запроса к серверу для обработки результата; функция будет вызвана со следующими параметрами:
- func(arg, responseText, responseXML, statusCode, statusText);
- arg - параметр arg, который был указан при вызове callServer()
- responseText - ответ сервера в виде текста (используется, если сервер возвращает не XML, а, к примеру, обычный HTML)
- responseXML - объект типа XMLDocument (используется, если сервер возвращает XML)
- statusCode - код завершения запроса (наиболее часто используемые коды: 200 - ОК, 404 - файл не найден, 401 - требуется авторизация; подробности - см. стандарт HTTP)
- statusText - текст с описанием ошибки (его можно показать пользователю, если код завершения не равен 200)
Приведем пример использования вышеописанных функций для загрузки и отображения внешнего HTML-документа в заданном участке текущей страницы:
<script type="text/javascript">
// ... сюда необходимо скопировать все вышеописанные функции ...
function showHTML(element, responseText, responseXML, statusCode, statusText) {
if (typeof(element)=="string")
element=document.getElementById(element);
if (statusCode==200 || statusCode==201) {
element.innerHTML=responseText;
}
else {
alert("Загрузить информацию не удалось: "
+statusText);
}
}
</script>
<input type="button" value="Загрузить!"
onclick="callServer(null, 'sample_doc.htm', null, null, showHTML, 'targetDiv')"/>
<div id="targetDiv">Здесь появится содержимое sample_doc.htm</div>
Ссылка на работающий пример: sample1.htm

Комментарии (22) к статье “Основы AJAX: Передача данных с помощью XMLHttpRequest”
У меня была проблема с кодировкой. Сервер выдавал sample_doc.htm в utf-8
Исправил положение заменив sample_doc.htm на sample_doc.php с таким кодом:
header(”Content-type: text/html; charset=windows-1251″);
echo “Это ответ в кириллице!”
интересно, а почему переданные параметры не видно в файле sample_doc.htm? (в моем случае php)
можно конечно сделать так:
callServer(null, ’sample_doc.htm?param=val’…..
но это же не наш метод, и к тому же метод “POST” не используется.
Что я делаю не так?
edyan,
Если Вы хотите передать параметры в sample_doc.php, то существует два метода:
1) callServer(’GET’, ’sample_doc.php?param=val’, null, null, func, arg);
2) callServer(’POST’, ’sample_doc.php’, ‘param=val’, ‘application/x-www-form-urlencoded;charset=windows-1251′, func, arg);
Чтобы второй вариант не глючил с кодировкой в Firefox, надо слегка подправить код функции callServer(). В текст статьи сейчас внесу соответствующие изменения (буквально вчера только отловил этот баг).
в функции callServer, на мой взгляд, не хватает преобразования data к необходимому виду. вот как это сделал я (предполагается, что data является массивом):
var post=”;
for(id in data){
post = post + id + “=” + encodeURIComponent(data[id]) + “&”;
}
забыл добавить, что далее вызов xmlReq.send идет с параметром post
xmlReq.send(post)
вроде вот так.
Логично. Но думается мне, что подобные преобразования лучше делать до вызова callServer(). Иначе функция утратит свою универсальность. Я, например, в качестве data передавал объект XML. Можно для удобства написать такую функцию:
function postServer(url, data, func, arg) {
var post=”;
for(id in data){
post=post+id+’='+encodeURIComponent(data[id])+’&';
}
return callServer(’POST’, ’sample_doc.php’, post, ‘application/x-www-form-urlencoded;charset=utf-8′, func, arg);
}
Обратите внимание, что encodeURIComponent() всегда использует кодировку UTF-8!
Имеется форма
Работает как видно через POST единственное что с нее приходит это seenform=forms. А как заставить ее еще отсылать par1 и par2 вводимые пользователем на сайте ?
function getForm(fobj) {
var str = “encode=utf8&”;
var ft = “”;
var fv = “”;
var fn = “”;
var els = “”;
for(var i = 0;i
К сожалению, WordPress, на котором в порядке эксперимента я сделал этот блог, не дает писать угловые скобки в комментариях. Мог бы просто эскейпить их, но он их удаляет. И кавычки портит.
Извините за неудобства, но не знаю, как это исправить.
Попробую вручную заескейпить: < и > - получилось! но геморройно…
PS. Вот поэтому не люблю готовый “стандартный” софт.
Возник вопрос с выполнением Ява-скриптов внутри полученных ответов с сервера (responseText).
как вариант нашол
function EvalAJAXScripts(obj)
{
scripts_arr = obj.getElementsByTagName(”script”);
for(i in scripts_arr) eval(scripts_arr[i].text);
}
http://www.habrahabr.ru/blog/AJAX/9063.html#habracut
но он неработает.(
Да, этот скрипт можно использовать лишь в качестве идеи. Чтобы он стал рабочим надо отлаживать по шагам. Сразу вижу одну конструкцию (.text), которая не во всех браузерах будет работать. И применять его надо не к responseText, а к responseXML.
Вообще, если нужно выполнять скрипты, получаемые с сервера, есть куда более элегантный подход: http://web-tec.info/2007/09/09/ajax_fundamentals_script_jsonp/
Здравствуйте, есть вопрос по этому скрипту, я сбираюсь передавать параметры в скрипт-обработчик, и задаю эти параметры переменными крпмеру:
var param = “123″;
И в фунции callServer добавил xmlReq.send(data+param)
Так все работает
Но никак не проходит такая конструкция:
var obj = document.getElementById(’search’);
var param = obj.value;
В ответ от скрипта получаю “undefined”
Тоесть я хочу извлекать передаваймеый параметр из формы на хтмл странице
На всякий случай уточню, что data - это тело POST-запроса. Если вы используете POST, надо задавать соответствующий тип в dataType. Для передачи параметров методом GET добавьте их к url, а не к data (соответствующим образом закодировав).
Другое замечание - нет никакой нужды что-то менять в функции callServer. Значение data приходит в нее извне. Вы можете заложить в data любые параметры перед обращением к callServer().
Если obj.value равен “undefined”, значит так оно и есть. Функция callServer() никакого отношения к этому не имеет.
Скопируйте, пожалуйста, сюда html-фрагмент, где присутствует поле формы, у которого id=”search”.
Убедитесь также, что параметр data определен при вызове callServer.
Так, начну по порядку.
По поводу data я все помниаю, что это тело POST-запроса я просто для удобства параметр сделал отдельной переменной… выглядит это так:
callServer(’POST’, ’sample_doc.php’, ’search=’, ‘application/x-www-form-urlencoded;charset=windows-1251′, showHTML, ‘targetDiv’)
…тоесть к “search=” добавляется param но это не суть важно, просто когда я param присваиваю определеное значение, напр. var param = “123″;
То принимающий скрипт его получает, и отсылает мне обратно.
Но когда делаю var param = obj.value
то обратно получаю “undefinded”
Вот кусок кода из sample.htm:
function getSerch() {
var obj = document.getElementById(’search’);
var param = obj.value;
}
…
Причем я сделал отдельный скрипт, в котором получал запросто значение из формы:
function getText()
{
var obj = document.getElementById(’search’);
var param = obj.value;
var div = document.getElementById(’targetDiv’);
div.innerHTML = param;
}
…
ммм, после “…” я пытался вставить хтмл код, но видимо движок блога его вырезал… попробую так:
это после первой функции
input type=”text” id=”search” size=”25″
input type=”button” value=”Загрузить!”
onclick=”getSearch(); callServer(’POST’, ’sample_doc.php’, ’search=’, ‘application/x-www-form-urlencoded;charset=windows-1251′, showHTML, ‘targetDiv’)”
это после второй:
input type=”text” id=”search” size=”25″
input type=”button” value=”Получить”
onclick=”getText()”
div id=”target” div
…убрал “” суть думаю осталась понятной
Трудно понять, не видя кода целиком.
Однако, функция getSerch() не выглядит законченной - переменная param в ней никак не используется, наверное не хватает “return param;” в конце.
Если хотите, чтобы переменная param была доступна вне функции getSearch, определите ее снаружи.
Дико извиняюсь, я функцию использовал на подобии процедуры :) она определена выше была, забыл это закинуть, много код изменял, и “сюда” попал такой вариант, в оригинале это выглядит так:
var param;
function getSearch() {
var obj = document.getElementById(’search’);
param = obj.value;
}
По приведенным фрагментам не могу найти ошибку. Нужен полный текст страницы, включая скрипты. Залейте куда-нибудь и пришлите ссылку.
Черт, пока в текстах копался, сам ошибку нашел…
Запутался в версиях файлов, у меня на сервере лежал вариант где getSearch() была после callServer() это была моя первая ошибка, которую я сам давно нашел, но забыл обновить файл на сервере, просто скрипты лежат у меня в отдельных файлах… а грешил я в основном на них. Извиняюсь за беспокойство.