Задайте свой вопрос о JavaScript на нашем форуме

Пользуемся AJAX-объектом

AJAX (Asynchronous JavaScript and XML) — термин, который не так давно вошел в лексикон создателей WEB-приложений. Он означает целую совокупность технологий, объединяемых в рамках одного интерфейса и позволяющих отправлять запросы без перезагрузки страницы.

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

AJAX-объект

// Базовый объект
var net = new Object();
// Состояния запроса
net.READY_STATE_UNINITIALIZED = 0;
net.READY_STATE_LOADING = 1;
net.READY_STATE_LOADED = 2;
net.READY_STATE_INTERACTIVE = 3;
net.READY_STATE_COMPLETE = 4;
// Конструктор
// key - Ключ запроса в массиве requestsHash
// method - метод отправки запроса (POST, GET)
// url - URL скрипта на сервере, который обработает запрос
// params - параметры запроса (test=1&flag=2)
// onload - callback-функция, обработчик после загрузки
// onerror - callback-функция, обработчик в случае ошибки
// contentType - тип контента запроса (text/html)
// headers - прочие заголовки, кроме content-type, например, Expires
net.ContentLoader = function(key, method, url, params, onload, onerror, contentType, headers) {
    this.hashKey = key;
    // Свойство для рапознавания браузеров, не поддерживающих request
    this.unrequestBrowser = false;
    // request - объект
    this.req = null;
    this.onload = onload;
    // Если её нет, вызывается дефолтный обработчик
    this.onerror = (onerror) ? onerror : this.defaultError;
    // Вызываем метод для генерации запроса
    this.loadXMLDoc(method, url, params, contentType, headers);
}
// Все методы записаны в прототип
net.ContentLoader.prototype = { // Methods
    // loadXMLDoc - метод, для генерации request-запроса
    loadXMLDoc : function(method, url, params, contentType, headers) {
        if (!method) method="GET";
        if (!contentType && method=="POST") contentType='application/x-www-form-urlencoded';
        if (window.XMLHttpRequest) {
            this.req=new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            this.req=new ActiveXObject("Microsoft.XMLHTTP");
        } else {
            this.unrequestBrowser = true;
            return;
        }
        if (this.req) {
            try {
                this.req.open(method,url,true);
                if (contentType){
                    this.req.setRequestHeader('Content-Type', contentType);
                }
                if (headers) {
                    for (var h in headers) {
                        this.req.setRequestHeader(h,headers[h]);
                    }
                }
                var loader=this;
                this.req.onreadystatechange=function() {
                    loader.onReadyState.call(loader);
                }
                this.req.send(params);
            } catch (err){
                this.onerror.call(this);
            }
        }
    },
    // onReadyState - метод для обработки ответов сервера
    onReadyState : function() {
        var req=this.req;
        var ready=req.readyState;
        if (ready==net.READY_STATE_COMPLETE) {
            var httpStatus=req.status;
            if (httpStatus==200 || httpStatus==0) {
                this.onload.call(this);
            } else {
                this.onerror.call(this);
            }
        }
    },
    // defaultError - метод обработки ошибок по умолчанию
    defaultError : function() {
        alert("error fetching data!"+"\n\nreadyState:"+this.req.readyState +"\nstatus: "+this.req.status+"\nheaders: "+this.req.getAllResponseHeaders());
    }
}
// Массив для хранения нескольких запросов
var requestsHash = [];
// Функция, создающая новый экземпляр объекта net.ContentLoader
// Записывает запросы в requestsHash
// Возвращает свойство unrequestBrowser
function setAjaxRequest(method, url, params, onload, onerror, contentType, headers) {
    // Check of necessary parameters
    if (!url) {
        alert("Necessary parameters are not specified");
        return;
    }
    requestsHash.push(new net.ContentLoader(requestsHash.length, method, url, params, onload, onerror, contentType, headers));
    return requestsHash[requestsHash.length - 1].unrequestBrowser;
}

Подготовка

Для создания так называемого асинхронного запроса и получения ответа потребуются некоторые условия:

1) Серверный скрипт, который примет запрос, обработает его и выдаст ответ. В качестве примера здесь будет использован PHP-скрипт, который отдает XML-дерево такого вида:

<xml>
    <result>Success!</result>
    <error />
</xml>

2) Функция, которая отправит запрос. Она уже есть (setAjaxRequest) и встроена в приведенный выше AJAX-объект, ей и воспользуемся.

3) Функции-обработчики, которые примут ответ (или возможную ошибку) и надлежащим образом отреагируют. Они будут вызваны как callback-функции. Это значит что this для них вернет ссылку на экземпляр объекта net.ContentLoader.

// Функция обработки ответа
function ansHandler() {
    // Для обработки ответа можно изпользовать два основных свойства request-объекта
    // responseText - вернет ответ в качестве текстовой переменной
    // responseXML - вернет XML-ответ
    // Последовательно воспользуемся обоими свойствами
    alert(this.req.responseText);
    // XML-структурой можно управлять более эффективно
    // Например, получать значения отдельных узлов
    var xml = this.req.responseXML.firstChild;
    if (xml.nodeType != 1) xml = xml.nextSibling; // fix for Opera
    var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;
    alert("result = " + result);
}
// Функция обработки ошибок
function errorHandler() {
    alert("При обработке запроса произошла ошибка, повторите попытку снова");
}

Формирование и отправка запроса

function doit() {
    var method = "GET";
    var url = "http://fastcoder.org/demo/ajaxDemo.php";
    var params = false; // Без параметров
    var onload = ansHandler;
    var onerror = errorHandler;
    var contentType = headers = false; // Без заголовков
    return setAjaxRequest(method, url, params, onload, onerror, contentType, headers);
}

И какой-нибудь HTML-элемент, например ссылку, для отправки запроса:

<a onclick="return doit();" href="#">Отправить запрос</a>

Демонстрация работы.

Замечания

  1. Браузер Opera ниже версии 8.0 не поддерживает request. Собственно для них и создавалось свойство unrequestBrowser, которое возвращается всеми функциями. Если вернется true, то произойдет простой переход по ссылке.
  2. Скрипт можно улучшить и расширить, но необходимый минимум (и даже больше) в этой статье имеется. Если вы нашли ошибки или пришли к выводу, что чего-то существенно не хватает - пишите.

Александр Бурцев 8 мая 2007

© Все права на данную статью принадлежат порталу fastcoder.org. Перепечатка в интернет-изданиях разрешается только с указанием автора и прямой ссылки на оригинальную статью. Перепечатка в печатных изданиях допускается только с разрешения редакции.

Комментарии

netruxa 4 декабря 2008, 13:03 #
не работает ссылка Демонстрация работы. Точнне там ошибка вылазит. Пробовал в Опера 9 и ИЕ 7
 
Комментарий удален администратором
 
Bur 4 декабря 2008, 13:15 #
Спасибо!
В примере была ошибка вызова, пофиксил.
В IE7, Opera 9, Safari 3 & FF2 работает - проверено.
 
 
Rambler's Top100 Flede HTML valid CSS valid