Использование XMLHttpRequest или AJAX своими руками.

Использование XMLHttpRequest или AJAX своими руками.

Понадобился мне вдруг класс для реализации AJAX.

Первая мысль естественно была - использовать jQuery.

Но к сожалению jQuery не удовлетворяет одному важному требованию - класс должен быть максимально "легким" :)

Пришлось сделать свою реализацию AJAX'а, а заодно решил написать мини-статью чтобы показать как это просто делается.

Всем привет.

Понадобился мне вдруг класс для реализации AJAX.

Первая мысль естественно была - использовать jQuery.

Но к сожалению jQuery не удовлетворяет одному важному требованию - класс должен быть максимально "легким" :)

Пришлось сделать свою реализацию AJAX'а, а заодно решил написать мини-статью чтобы показать как это просто делается.

Итак, задача состоит в том, чтобы сделать "легкий" (малый размер и потребление памяти), но функциональный класс, реализующий асинхронные запросы к серверу - AJAX, в том числе обмен по протоколу JSON.

Интерфейс класса должен должен быть максимально близким к jQuery т. к. он самый удобный с моей точки зрения.

Приступим :)

Первое что нужно сделать - объявить наш класс. Назовём его CAjax.

К слову, классы в JavaScript можно объявлять многими способами. Выберем один из самых удобных и эффективных:

Листинг : Объявление класса и основных свойств with( CAjax = function(){} ){ prototype. hRqst = null; // - Объект XMLHttpRequest prototype. isAborting = false; // - Флаг заврешения по запросу

}

Все методы и свойства нужно объявлять такм же, внтури скобок.

Теперь сделаем функции для инициализации и удаления объекта hRqst ( XMLHttpRequest )

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

Листинг : Метод инициализации класса

//! Инициализация prototype. init = function(){ if (window. XMLHttpRequest) { prototype. hRqst = new XMLHttpRequest();

} else { prototype. hRqst = null;

}

}

Объекта window. XMLHttpRequest может и не быть в засимости от браузера, поэтому рекомендуют делать такую конструкцию:

Листинг : Универсальная инициализация function createRequestObject(){ if (XMLHttpRequest == undefined) {

XMLHttpRequest = function() { try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch(e) {} try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch(e) {} try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) {} try { return new ActiveXObject("Microsoft. XMLHTTP"); } catch(e) {} throw new Error("This browser does not support XMLHttpRequest.");

};

} return null;

}

Смысл в переборе всех возможных вариантов создания XMLHttpRequest. Вдруг один из них сработает :)

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

Листинг : Метод удаления объекта XMLHttpRequest

//! Очистка ресурсов prototype. dispose = function(){ if( prototype. hRqst == null ) return; delete prototype. hRqst; prototype. hRqst = null;

}

А теперь самая главная функция - отправка запроса и получение ответа.

Для начала просто объявим её

Листинг : Объявление метода отправки запроса

//! Отправка запроса и получение ответа prototype. send = function( Opt ){

}

На вход функция будет принимать хеш-таблицу с параметрами:

Листинг : Параметры var Parameters = { method: "GET", // - Метод передачи данных url: "http://av-school. ru", // - URL запроса async: true, // - Выполнить асинхронно dataType: "json", // - Тип возвращаемых данных ( plain - как есть ) opened: function(){ // - Обработчик открытия соединения

// - Вызывается при открытии соединения alert( "Opened" );

}, dataTX: function(){ // - Обработчик отправки данных

// - Вызывается при отправке данных на сервер alert( "Sending..." );

}, dataRX: function(){ // - Обработчик приёма данных

// - Вызывается при приёме данных alert( "Recieving..." );

}, complete: function( data ){ // - Обработчик завершения приёма данных

// - Вызывается при завершении приёма, озвращает принятые данные alert( data. message );

}, error: function( code, text ){ // - Обработчик ошибки

// - Вызывается при ошибке alert( "Error " + code + ": " + text );

}

}

Приступим к реализации функции.

Сначала базовая проверка параметров и состояния.

Листинг : Проверка парметров

// - Проверка инициализации класса if( prototype. hRqst == null ){ if( typeof( Opt. error ) == "function" ) Opt. error( -3, "Not initialized" ); return;

}

// - Проверка основных параметров if( Opt. url == "undefined" || Opt. method == "undefined" ){ if( typeof( Opt. error ) == "function" ) Opt. error( -4, "Invalid arguments" ); return;

}

// - Установка значений по умолчанию if( Opt. async == "undefined" ) Opt. async = true; if( Opt. dataType == "undefined" ) Opt. dataType = "plain";

// - Установка флага отмены в false prototype. isAborting = false;

XMLHttpRequest умеет через событие сообщать о изменение состояния запроса.

Наша задача заключается в установке обработчика на это событие и вызов внешних обработчиков при возникновении соотвествующего события.

Листинг : Обработчик изменения состояния XMLHttpRequest

//! Установка отбработчика изменения состояния prototype. hRqst. onreadystatechange = function() { var state = prototype. hRqst. readyState

// --- Открытие соединения if( state == 1 ){ if( typeof( Opt. opened ) == "function" ) Opt. opened();

// --- Отправка даных

} else if( state == 2 ){ if( typeof( Opt. dataTX ) == "function" ) Opt. dataTX();

} else if ( state == 3 ){ if( typeof( Opt. dataRX ) == "function" ) Opt. dataRX();

// --- Данные получены

} else if ( state == 4) {

// - Проверка на отмену запроса if( prototype. isAborting ) { if( typeof( Opt. error ) == "function" ) Opt. error( -2, "Request aborted" ); return;

}

// - Вызываем обработчик if( typeof(Opt. complete) == "function" ){ var data = prototype. hRqst. responseText; var code = prototype. hRqst. status;

// - OK if( code == 200 ){ if( Opt. dataType == "plain" ){ Opt. complete( data );

} else if ( Opt. dataType == "json" ){ var json = null; try{ json = eval( "(" + data + ")" );

}catch(e){ if( typeof( Opt. error ) == "function" ) Opt. error( -1, "Invalid JSON format" ); return;

}

Opt. complete( json );

}

} else { if( typeof( Opt. error ) == "function" ) Opt. error( code, prototype. statusText );

}

}

}

};

Вот собственно и всё.

При вызове обработика, просто смотрим какой под пришел и вызываем соотвествующий наш обработчик, переданый в параметрах.

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

Теперь осталось только открыть соединение и отправить запрос:

Листинг : Отправка запроса

// - Открываем соединение и отправлем запрос prototype. hRqst. open( Opt. method, Opt. url, Opt. async ); prototype. hRqst. send();

... и последняя функция, предназначенная для отмены асинхронного запроса:

Листинг : Отмена запроса

//! Отмена запроса prototype. abort = function(){ if( prototype. hRqst == null ) return; prototype. isAborting = true; prototype. hRqst. abort();

}

Вот и всё :)

Использовать класс можно так:

( на примере обращения к Google Translate )

Листинг : использование класса

// - Слово, которе var Text = "virus";

// - Создаём объект класса var hAjax = new CAjax();

// - Инициализируем hAjax. init();

// --- Отправка запроса на сервер hAjax. send({ method: "GET", url: "http://translate. google. com/translate_a/t? client=t&text=" + encodeURIComponent( Text ) + "&sl=en&tl=ru&pc=1", async: false, dataType: "json", opened: function(){ alert( "Opened." );

}, dataTX: function(){ alert( "Sending..." );

}, dataRX: function(){ alert( "Recieving...");

}, complete: function( data ){ alert( "Complete" ); if( data. dict!= null ){ alert( "Translation: " + data. dict[0].terms[0] );

}else{ alert( "Translation: " + data. sentences[0].trans );

}

// - Удаляем объект hAjax. dispose();

}, error: function( code, text ){ alert( "Error " + code + ": " + text );

}

});

И полный текст класса:

Листинг : Полный текст класса with( CAjax = function(){} ){ prototype. hRqst = null; // - Объект XMLHttpRequest prototype. isAborting = false; // - Флаг заврешения по запросу

//! Инициализация prototype. init = function(){ if (window. XMLHttpRequest) { prototype. hRqst = new XMLHttpRequest();

} else { prototype. hRqst = null;

}

}

//! Отправка запроса и получение ответа prototype. send = function( Opt ){

// - Проверка инициализации класса if( prototype. hRqst == null ){ if( typeof( Opt. error ) == "function" ) Opt. error( -3, "Not initialized" ); return;

}

// - Проверка основных параметров if( Opt. url == "undefined" || Opt. method == "undefined" ){ if( typeof( Opt. error ) == "function" ) Opt. error( -4, "Invalid arguments" ); return;

}

// - Установка значений по умолчанию if( Opt. async == "undefined" ) Opt. async = true; if( Opt. dataType == "undefined" ) Opt. dataType = "plain";

// - Установка флага отмены в false prototype. isAborting = false;

//! Установка отбработчика изменения состояния prototype. hRqst. onreadystatechange = function() { var state = prototype. hRqst. readyState

// --- Открытие соединения if( state == 1 ){ if( typeof( Opt. opened ) == "function" ) Opt. opened();

// --- Отправка даных

} else if( state == 2 ){ if( typeof( Opt. dataTX ) == "function" ) Opt. dataTX();

} else if ( state == 3 ){ if( typeof( Opt. dataRX ) == "function" ) Opt. dataRX();

// --- Данные получены

} else if ( state == 4) {

// - Проверка на отмену запроса if( prototype. isAborting ) { if( typeof( Opt. error ) == "function" ) Opt. error( -2, "Request aborted" ); return;

}

// - Вызываем обработчик if( typeof(Opt. complete) == "function" ){ var data = prototype. hRqst. responseText; var code = prototype. hRqst. status;

// - OK if( code == 200 ){ if( Opt. dataType == "plain" ){ Opt. complete( data );

} else if ( Opt. dataType == "json" ){ var json = null; try{ json = eval( "(" + data + ")" );

}catch(e){ if( typeof( Opt. error ) == "function" ) Opt. error( -1, "Invalid JSON format" ); return;

}

Opt. complete( json );

}

} else { if( typeof( Opt. error ) == "function" ) Opt. error( code, prototype. statusText );

}

}

}

};

// - Открываем соединение и отправлем запрос prototype. hRqst. open( Opt. method, Opt. url, Opt. async ); prototype. hRqst. send();

}

//! Отмена запроса prototype. abort = function(){ if( prototype. hRqst == null ) return; prototype. isAborting = true; prototype. hRqst. abort();

}

//! Очистка ресурсов prototype. dispose = function(){ if( prototype. hRqst == null ) return; delete prototype. hRqst; prototype. hRqst = null;

}

}


Карта сайта


Информационный сайт Webavtocat.ru