Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Коректность алгоритма (https://javascript.ru/forum/misc/28813-korektnost-algoritma.html)

Vit 03.06.2012 18:51

Коректность алгоритма
 
Всем доброго.
Скажите пожалуйста насколько корректен выбранный мною алгоритм с точки зрения "замусоривания памяти"

Есть конструктор:
function go(){
 return{
   Send:function (param,OnOk,OnFail){
     var _ajax=ajax();
	 if(!_ajax){alert("Браузер не поддерживает AJAX"); return;}
	 _ajax.open("GET",serv+'?'+param,true);
	 _ajax.onreadystatechange=function(){
		if (_ajax.readyState == 4){ 
		  if(_ajax.status==200){
		   var a=_ajax.responseText.substring(0,6);
		   if(a!='Error-') OnOk(_ajax.responseText)
		   else OnFail(_ajax.responseText);
		  };
		  if (_ajax.status!=200){OnFail("Неудачная попытка связи.");}
		 }
		};
	 _ajax.send(null);
   }
 }
}

Где ajax() - функа создаюшая объект XMLHttpRequest.

Вызов производится так:
var t=go();
 t.Send(p,function(s){alert("Удачно "+s);},function(s){alert("Не удачно "+s);});

p - параметры запроса

Не попадаю ли я таким методом на утечку памяти?
Ведь я фактически создаю объекты но не освобождаю явно после отработки?

Правильно ли я поступаю или есть другой более лучший способ, который не заставит браузер оставлять мусор?

melky 03.06.2012 19:15

Цитата:

Сообщение от Vit
Не попадаю ли я таким методом на утечку памяти?
Ведь я фактически создаю объекты но не освобождаю явно после отработки?

в js есть сборщик мусора, так что опасаться не стоит. стоит только избегать замыканий, где они не нужны.

а вот этого лучше избегать, т.к. переменные не будут очищаться до того, как функция обработки завершения запроса не прекратит работу.
_ajax.onreadystatechange=function(){
		if (_ajax.readyState == 4){

лучше сделать так - в this будет XMLHttpRequest, для которого в текущий момент обрабатывается событие. всё так же, как и в элементах.
_ajax.onreadystatechange=function(){
		if (*!*this*/!*.readyState == 4){

а лучше - даже так - вынести обработчик куда-нибудь в долгую память.
function handler(){
    if (this.readyState == 4){ 
    //......
}

// function go ....
    _ajax.onreadystatechange = *!*handler*/!*;

devote 03.06.2012 19:17

Цитата:

Сообщение от melky
лучше сделать так:
_ajax.onreadystatechange=function(){         if (this.readyState == 4){

в ИЕ это вызовет ошибку. Так как this там не будет равен xhr

melky 03.06.2012 19:30

Цитата:

Сообщение от devote (Сообщение 178528)
в ИЕ это вызовет ошибку. Так как this там не будет равен xhr

Вот, посмотрите
http://jsfiddle.net/yPKkJ/
В IE10 в режиме эмуляции IE8,IE7 всё нормально.

Или Вы ActiveX компонент имели в виду?

devote 03.06.2012 19:30

melky,
хотя эта проблема наблюдается в ИЕ6 тогда да, можно поставить this. Я что-то старой инфой оперирую :)

devote 03.06.2012 19:31

Цитата:

Сообщение от melky
Вот, посмотрите

да я только что проверил в локалке.. ИЕ6 в попе, остальные норм.

Vit 03.06.2012 19:45

Цитата:

Сообщение от devote (Сообщение 178537)
ИЕ6 в попе, остальные норм.

Ишачок меня мало интерсует в рамках конкретно этого проекта.
По крайней мере устаревшие браузеры уж точно не интересуют.
Цитата:

вынести обработчик куда-нибудь в долгую память.
А почему?
И как правильно описать handler(), дабы он входил в состав объекта, и видел OnOk и OnFail?

melky 03.06.2012 20:35

Цитата:

Сообщение от Vit
А почему?

Потому что когда Вы каждый раз пишете el.onclick = function(){ ..., Вы каждый раз убиваете котёнка создаёте новую функцию. А делая, как я показал, Вы используете одну каждый раз.

Цитата:

Сообщение от devote
да я только что проверил в локалке.. ИЕ6 в попе, остальные норм.

Я не пишу под него, как и под FF 3.6. Я в стаде :).

Цитата:

Сообщение от Vit
И как правильно описать handler(), дабы он входил в состав объекта, и видел OnOk и OnFail?

Самое простое - записать их в объект какой-нибудь, а его уже сохранить в замыкании.
http://jsfiddle.net/yPKkJ/2/
Боялся, что IE не понравится custom свойство id ... но, вроде, пережевал.
(function() {

    var running = {};

    function noop() {}

    function handler() {
        if (this.readyState === 4) {
            (running[this.id][this.status === 200 ? "onsuccess" : "onerror"] || noop).call(this);
            delete running[this.id]; // убиваем сами обработчиков. не нужны уже.
        }
    }

    window.send = function(url, method, data, onsuccess, onerror) {
        var req = new XMLHttpRequest();
        req.open(method, url, true);
        req.onreadystatechange = handler;
        req.send(data);
        req.id = (Math.random() * 1e5 | 0).toString(32); // случайна последовательность англ. букв и цифр. 
        running[req.id] = { // сохраняем, пока не понадобятся
            "onsuccess": onsuccess,
            "onerror": onerror
        };
    }
})();

Vit 03.06.2012 21:03

Т.е. мне лучше описать handler как private метод объекта, и присваивать его onreadystatechange, дабы каждый раз не "создавать" анонимную функцию.
При этом поскольку сам handler будет принадлежать объекту я смогу в нем вызывать мои OnOk и OnFail?
Верно я понял?

melky 03.06.2012 21:12

Цитата:

Сообщение от Vit
Верно я понял?

Если взять объект, "которому принадлежит handler", за req, а "смогу вызывать onOk .." - за итог, то да, верно.


Часовой пояс GMT +3, время: 12:10.