Модераторы: Sardar, Aliance
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> JS + OOP + AJAX 
:(
    Опции темы
drainme
Дата 12.8.2010, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 21.4.2009

Репутация: нет
Всего: нет



Всем привет , столкнулся с проблемой ооп в js. Есть псевдо класс, описывающий подключение в фоновом режиме - ajax запрос проще говоря. Проблема судя по всему в прототипах, ибо без классов все работает, но мне хочется разобраться и собрать библиотеку для ajax. Проблема в функции handle_response (33-45), там не видно свойства request. Еще есть сомнение по поводу onreadystatechange(25) - возмонжно я неправильно задал callback.  smile 
Код

function http_request(){
    this.request = null;
    this.callback= null; //function that runs after handling response
    this.stack = new Array();
    
    try {
        this.request = new XMLHttpRequest();
    } catch (e) {
        try {
            this.request = new ActiveXObject();
        }catch(e){}
    }
    if (this.request == null) throw('couldnot create request object');
}

http_request.prototype.send = function(method,url,data_array,callback) {
    if(method  && url){
        this.push_into_stack(method, url, data_array, callback);
    }
    
    if(this.request.readyState == 0 || this.request.readyState == 4){
        var settings = this.pop_out_of_stack();
        
        this.request.open(settings['method'], settings['url'], true);
        this.request.onreadystatechange = this.handle_response;
        this.callback = settings['callback'];
        this.request.send(this.prepare_data(settings['data_array']));
    }else if(this.stack.length > 0){
        setTimeout('this.send()', 3000);
    }
};

http_request.prototype.handle_response = function() {
    if(this.request.readyState == 4){
        if(this.request.status == 200){
            this.execute_response();
        }else{
            throw ('There was a mistake during ajax transfer.');
        }
    }else{ // delete
        alert(this.request.status.toString());
        alert(this.request.statusText);
        
    }
};

http_request.prototype.execute_response = function() {
    var response = this.request.responseText; // redo
    if(this.callback != null){
        this.callback(response);
    }
    if (this.stack.length > 0) {
        this.send();
    }
};

/* --- helpers --- */
http_request.prototype.prepare_data = function(data) {
    var str = new String;
    for ( var key in data) {
        str +=  escape(key)+'='+escape(data[key])+'&';
    }
    return str.substring(0, str.length - 1);
};

http_request.prototype.push_into_stack = function(method,url,data_array,callback){
    var tmpArray = new Array();
    tmpArray['method'] = method;
    tmpArray['url'] = url;
    tmpArray['data_array'] = data_array;
    tmpArray['callback'] = callback;
    this.stack.push(tmpArray);
};

http_request.prototype.pop_out_of_stack = function() {
    return this.stack.pop();
};

function text_callback(text){
    alert(text);
}

try{
    var request = new http_request();
    request.send("GET","http://virtual-dummy1/1.txt");
}catch(e){
    alert(e.toString());
}




Это сообщение отредактировал(а) drainme - 12.8.2010, 16:03
PM MAIL Skype   Вверх
Amphiluke
Дата 12.8.2010, 19:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


   ☽
***


Профиль
Группа: Завсегдатай
Сообщений: 1253
Регистрация: 26.8.2009

Репутация: 39
Всего: 112



Цитата(drainme @  12.8.2010,  19:54 Найти цитируемый пост)
this.request.onreadystatechange = this.handle_response;

Попробуйте вместо этого так:
Код

var thisAlias = this;
this.request.onreadystatechange = function() {thisAlias.handle_response();}

Дело в том, что в обработчиках событий ключевое слово this указывает на объект, в котором происходит событие, в данном случае на объект XMLHttpRequest, а не на ваш собственный объект http_request.

PM   Вверх
IDVsbruck
Дата 12.8.2010, 20:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 778
Регистрация: 12.11.2006

Репутация: 7
Всего: 22



Плохой пример. Переменная к моменту срабатывания события может быть недоступна. Надо использовать передачу параметров, а еще лучше замыкание.
PM MAIL   Вверх
Amphiluke
Дата 12.8.2010, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


   ☽
***


Профиль
Группа: Завсегдатай
Сообщений: 1253
Регистрация: 26.8.2009

Репутация: 39
Всего: 112



А чем это не замыкание? Цепочка областей видимости анонимной функции, назначаемой свойству onreadystatechange, включает объект вызова внешней функции. Сборщик мусора не удалит переменную thisAlias, пока вложенная функция будет ссылаться на объект вызова. Нет?

Это сообщение отредактировал(а) Amphiluke - 12.8.2010, 21:18
PM   Вверх
drainme
Дата 13.8.2010, 08:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 21.4.2009

Репутация: нет
Всего: нет



Большое спасибо за разъяснения, сам бы еще долго искал решение, но вот что интересно с моим прежним кодом" = this.handle_response", функция срабатывает(просто алерт вставил для теста), по поводу xmlhttpobject'a логично и тему можно закрывать, но почему this работает все-таки интересно

Это сообщение отредактировал(а) drainme - 13.8.2010, 10:17
PM MAIL Skype   Вверх
IDVsbruck
Дата 13.8.2010, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 778
Регистрация: 12.11.2006

Репутация: 7
Всего: 22



Цитата(Amphiluke @  12.8.2010,  21:16 Найти цитируемый пост)
А чем это не замыкание? Цепочка областей видимости анонимной функции, назначаемой свойству onreadystatechange, включает объект вызова внешней функции. Сборщик мусора не удалит переменную thisAlias, пока вложенная функция будет ссылаться на объект вызова. Нет?

Извини, дорогой ... Для раздела "JavaScript для новичков" пример вполне дееспособный, но если мы говорим о более серьезном подходе, то вариант никудышний.
Я молчу о том, что переменная thisAlias теоретически может быть переопределена на момент срабатывания хандлера - это, конечно же, маловероятно, но надежность кода страдает.
А вот то, что анонимная функция, назначенная onreadystatechange, НИЧЕГО пока не знает о своей "начинке" - это факт достаточно известный smile, поэтому GC может и подчистить приватную переменную. В данном случае спасает (может спасать) только то, что внутренний GC в JavaScript срабатывает по таймеру, а ответ с сервера в примере приходит быстрее. Но согласись, это же не решение задачи - так работать на грани фола. Именно для этого и придумали замыкания - чтобы отдать значение доступной переменной внутреннему механизму, и дальше ее не трогать и позволить удалиться. Советую уделять более пристальное внимание надежности и универсальности кода.

Добавлено через 11 минут и 9 секунд
Цитата(drainme @  13.8.2010,  08:08 Найти цитируемый пост)
Большое спасибо за разъяснения, сам бы еще долго искал решение, но вот что интересно с моим прежним кодом" = this.handle_response", функция срабатывает(просто алерт вставил для теста), по поводу xmlhttpobject'a логично и тему можно закрывать, но почему this работает все-таки интересно

Там где назначен this.handle_response, он существует, так как this в данном случае ссылается на объект типа http_request, то есть противоречий нет. А когда позже идет ссылка на this.request, то у handle_response такого свойства/функции нет. Можно получить через parent.request или обратиться просто через request - не стал пристально смотреть код и тестировать его, но думаю, это свойство (без this) будет доступно.
PM MAIL   Вверх
Amphiluke
Дата 13.8.2010, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


   ☽
***


Профиль
Группа: Завсегдатай
Сообщений: 1253
Регистрация: 26.8.2009

Репутация: 39
Всего: 112



IDVsbruck, спасибо, а вы не могли бы набросать примерчик?  smile  Даже отвлечемся от кода топикстартера. Просто какой-нибудь простой пример, в котором метод пользовательского объекта служил бы обработчиком события и при этом имел доступ ко всем свойствам объекта а также к экземпляру объекта Event, передаваемого в обработчик.

Вот я начну потихоньку.
Код

function CustomObj() { // конструктор
    this.prop = "this is object property";
}
CustomObj.prototype.methodHandler = function(e) {
    alert("event target: " + e.target);
    alert("object property: " /* + здесь нужно считать значение св-ва prop */);
}

/* ... */

var obj = new CustomObj();
document.addEventListener("click", obj.methodHandler, false); // или как-нибудь по-другому...



Можно сделать и так (типа еще «замыкание»  smile ):
Код

function CustomObj() { // конструктор
    this.prop = "this is object property";
}
CustomObj.prototype.methodHandler = function(e, __instance) {
    alert("event target: " + e.target);
    alert("object property: " + __instance.prop);
}
CustomObj.prototype.returnClickHandler = function() {
    var __instance = this;
    var __method = this.methodHandler;
    return function(e) { __method(e, __instance); };
}

var obj = new CustomObj();
document.addEventListener("click", obj.returnClickHandler(), false);

но это же опять неправильно, по-вашему?
Напишите, please, как вам видится наиболее грамотное решение.

Добавлено через 3 минуты и 11 секунд
Именно для этой простой задачки.
PM   Вверх
ksnk
Дата 13.8.2010, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 48
Всего: 386



drainme
там еще есть строка 29
Код

   setTimeout('this.send()', 3000);

оно работало когда-нибудь? Вот сюда тоже надо бы замыкание поставить.

Цитата(drainme @  13.8.2010,  08:08 Найти цитируемый пост)
 что интересно с моим прежним кодом" = this.handle_response", функция срабатывает(просто алерт вставил для теста)

проблема в том, что в этом случае при выполнении функции this будет указывать в объект window, а не в http_request



--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
IDVsbruck
Дата 13.8.2010, 21:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 778
Регистрация: 12.11.2006

Репутация: 7
Всего: 22



Цитата(Amphiluke @  13.8.2010,  15:57 Найти цитируемый пост)
Напишите, please, как вам видится наиболее грамотное решение.

Добавлено через 3 минуты и 11 секунд
Именно для этой простой задачки.

Человек дурню написал, а мы с тобой должны на поводу вестись? Хотя бы: 
Цитата(drainme @  12.8.2010,  15:54 Найти цитируемый пост)
Есть псевдо класс, описывающий подключение в фоновом режиме


Не считаю, что я должен учавствовать в споре "а слабо?" с заведома абсурдными данными.
В js (и фреймворках) мы же не переопределяем функции для обработчика, а создаем их и назначаем. Почему тут должно быть иначе? - Зачем делать обработчик в составе прототипа - дурня же! Если функция обработчика выполняет какие-то узкоспециализированные действия внутри класса, то делается переменная класса, указывающая на внутреннюю функцию, или еще лучше - грамотно написанная анонимная функция (действие-то внутреннее, можно постараться, чтобы казусов с загрязнение памяти не было).
Поэтому я принципиально не хочу поддерживать данный спор (дабы не было мысли, что я не могу или не знаю как и что делать - слава аллаху, за несколько лет работы школу получил неплохую).

PM MAIL   Вверх
Amphiluke
Дата 13.8.2010, 22:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


   ☽
***


Профиль
Группа: Завсегдатай
Сообщений: 1253
Регистрация: 26.8.2009

Репутация: 39
Всего: 112



Ладно, ясно… что ничего не ясно  smile . Впрочем, причем здесь «а слабо?»? Я просто хотел увидеть кусок грамотного кода для дальнейших размышлений… о философии smile Разве кто-то спорит? Просто идет обмен информацией с целью поиска оптимальных путей.

Это сообщение отредактировал(а) Amphiluke - 13.8.2010, 22:11
PM   Вверх
IDVsbruck
Дата 14.8.2010, 00:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 778
Регистрация: 12.11.2006

Репутация: 7
Всего: 22



Ага, а ну-ка, для начала покажи мне пример создания в javascript'е псевдо-класса smile
PM MAIL   Вверх
Amphiluke
Дата 14.8.2010, 08:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


   ☽
***


Профиль
Группа: Завсегдатай
Сообщений: 1253
Регистрация: 26.8.2009

Репутация: 39
Всего: 112



Ну, вообще-то определение «псевдокласса» в Javascript как раз и осуществляется путем написания функции-конструктора, которая создает и инициализирует нужные атрибуты экземпляра, а также добавлением свойств и методов к объекту-прототипу (см. предыдущие сообщения). Ясно, что Javascript пока не обеспечивает поддержку классов, как этого, может быть, хотелось бы. Отсюда, наверное, присказка «псевдо-». Но такая терминология, вообще говоря, используется с указанными оговорками. Так что не стоит придираться к словам. Не об этом же речь. smile

Это сообщение отредактировал(а) Amphiluke - 14.8.2010, 08:37
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1197 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.