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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Цепочка функций, последовательное выполнение (chaining) 
:(
    Опции темы
Dr.Zlo
Дата 29.1.2008, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Я избавился от ошибки следующим образом:

Код

        x.next=(function(){
            var xx=x; 
            return function(){
                xx.stop();
        if (xx.length==0) return false; // Если цепочка закончилась, уходим
                xx.exec(xx.shift());
                return xx;
            }
        })() ;


После этого нормально стало всё работать и не косячить после последнего элемента. Если честно я до сих пор до конца не втыкаю как работает твой chain, это решение я нашёл интуитивно.
Но по ходу ты пофиксил тем же способом и ужё ушёл намного дальше в разработку chain smile
Вечером посмотрю и протестю твой новый вариант.
PM MAIL   Вверх
AKS
Дата 29.1.2008, 20:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Участник форума
**


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

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



Цитата(ksnk @  29.1.2008,  17:24 Найти цитируемый пост)
var x =(this instanceof Array)?this:new Array();

Смотрю и не могу понять - когда условие this instanceof Array будет истинным? Когда Вы "провернете" трюк из книжки?

PM MAIL   Вверх
ksnk
Дата 29.1.2008, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



AKS, Нееееее! Тут как раз все значительно интереснее  ;-) объект chain это и ЕСТЬ настоящий массив честно сделанный через new Array!

Добавлено через 42 секунды
this instanceof Array - проверка на то, вызывают ли нас первый раз. Тогда this указывает на объект window


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


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


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

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



AKS, Впрочем, Вы как всегда правы! smile Проверка идиотская и в этом варианте лишняя. В оправдание могу предъявить цепочку соображений, которая привела к появлению этого кода.

Первоначальное решение было опубликовано выше несколькими постами и последующие варианты лишь "облагораживали" его.

Проявившееся желание написать chain(x).chain(y).chain(z)... породило совершенно логичную мысль о том, что каждая функция chain выдает некий объект как результат. причем первый chain в цепочке должен его (этот объект) породить. А так как по сути первый и последующие элементы цепочки одинаковы по входным параметрам, то родилась уникальная мысль написать конструкцию 
function chain(){..var x = new chain().... this.chain=chain/* Yoooo!!!*/ ...}; chain.prototype=new Array();,
 все в одном флаконе. ;-)
Когда пришла пора "со всей этой фигней взлетать", возникла задача по определению контекста вызова chain(), new chain(), и .chain'а, рудиментарное наследие от которой до сих пор сидела в коде. по дороге напоролся на "баг", не позволяющий наследоваться от Array запланированным способом. Хорошо, что внезапно посетивший меня приступ здравого смысла заставил несколько оптимизировать код, но, к сожалению, не до конца.
Так что, AKS, спасибо!


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


Новичок



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

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



ksnk, вчера внедрил chain в довольно большое приложение. Всё отлично работает, 

Но есть несколько пожеланий. 

1. Иногда нужно собрать chain по кусочкам, и только потом выполнить, или к примеру иногда удобней объявить chain где-нибудь в начале скрипта, а вызывать в нужных местах. Допустим у нас есть задача: для всех чётных элементов списка выполнить функцию по цепочке. Вот как я это вижу: 
 
Код

var objs=document.getElementsByTagName('li');
var x=new Chain();
for(var i=0; i<objs.length; i++){
    if ((Math.floor((i+1)/2)-Math.floor((i)/2))==0){
        var obj = objs[i]
        x.chain(animate, obj);
    }
}
x.run();


Было бы прикольно, если бы такая конструкция работала

2. После завершения chain лучше избавляться от созданного массива (обnullять его, что-ли), ведь если все эти массивы будут висеть в памяти, после нескольких вызовов chain скрипт будет заметно тормозиться
PM MAIL   Вверх
ksnk
Дата 30.1.2008, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Dr.Zlo @  30.1.2008,  09:32 Найти цитируемый пост)
 Иногда нужно собрать chain по кусочкам, и только потом выполнить,

До тех пор пока не вызван метод run, chain остается "не запущеным".
Цитата(Dr.Zlo @  30.1.2008,  09:32 Найти цитируемый пост)
После завершения chain лучше избавляться от созданного массива
 Факт вызова очередной функции chain'а "автоматически" выкидывает первый элемент... как рожок в автомате - патрон стреляет - гильза вылетает smile

imho, если переписать вашу конструкцию вот так
Код

var objs=document.getElementsByTagName('li');
var x=Chain(); // идеология поменялась... new вызывать не надо...
for(var i=0; i<objs.length; i++){
    if (!( i | 1)) { // четные
        x.chain(animate, objs[i]);
    }
}
x.run();

То я не вижу причин почему бы она не заработала...

т.е. Все уже сделано ;-)

Это сообщение отредактировал(а) ksnk - 30.1.2008, 09:49


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


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


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

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



Честно говоря меня преследует вопрос эстетический ;-) Удобно ли то, что "первая" функция называется Chain (с большой буквы). Можно было бы ради единообразия назвать ее chain (с маленькой), как и "собственный" метод. На каком-то этапе мне показалось идеологически более верно то, что первый элемент цепочки пишется с большой буквы. Правда до серьезного практического применения этой "идеологии" я пока не добрался. 


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


Новичок



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

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



По поводу именования. 
Думаю по фэн-шую было бы правильно создавать цепь, потом присоединять к ней звенья. Цепь по-английски chain, по поводу звеньев яндекс словари говорят следующее:

звено
ср.

1) link

2) (механизма или структуры) unit, section; part, branch

3) team, group, unit

4) (самолетов) flight

5) воен. level, echelon, squad 

Так как с link будут несколько другие ассоциации, то можно взять unit для определения звена цепи. 
В итоге можно договориться использовать конструкцию вроде:

chain().unit(func1, param1).unit(func2, param2).unit(func3, param3).run();

В крайнем случае оставить всё как есть, только избавиться от Chain с большой буквы, он путает и сбивает с толку, как мне кажется
PM MAIL   Вверх
ksnk
Дата 30.1.2008, 11:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



ok! Надо будет при случае поменять большую букву...
Насчет unit'а - я против... ;-) ; - я предполагал первонально, что будет вот так
chain(func1, param1).chain(func2, param2).chain(func3, param3).run(); Единая сущьность для первой и последующих итераций... Imho, пусть так и остается. Всех изменений в скрипте, если надо - переназвать "головную" функцию...

Это сообщение отредактировал(а) ksnk - 30.1.2008, 11:04


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


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

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



Уже вторая страница, а я что-то не пойму сути вопроса... smile
Оно?
Код

        function chain(func) {
            var prev = this; //ссылка на предыдущую chain
            var args = []; //из-за особого чувства юмора у ECMA, arguments это не Array, метода .slice нет...
            for(var i = 1; i < arguments.length; i++) args.push(arguments[i]);

            var hnd = function() {
                if(prev instanceof Function) prev(); //у самого первого chain здесь будет window или любой другой объект, чьим методом была chain
                func.apply(window, args);
            }

            hnd.chain = arguments.callee; //цепочка
            return hnd;
        }

        chain(alert, "OK").chain(alert, "cool")(); //результат chain - функция, не забываем её вызвать



--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
Dr.Zlo
Дата 30.1.2008, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Всё-таки отсроченный запуск chain не работает, я тестировал, просто не запускается и всё. Вот исходник:

Код

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=windows-1251">
<script language="javascript" src="jquery.js"></script>
<script>
$(document).ready(function(){
    var objs=document.getElementsByTagName('li');
    var x=Chain(); 
    for(var i=0; i<objs.length; i++){
        if ( i & 1) { // твой вариант определения чётности был не правильный
            //cur_li(objs[i])
            x.chain(cur_li, objs[i]);
        }
    }
    x.run();
})

function cur_li(obj){
    $(obj).animate({'fontSize': 40}, 1000, 'linear', function(){
        if (cur_li.next) cur_li.next();
    })
}

</script>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
</ul>
</body>
</html>


Кстати, ещё одна интересная тема для размышлений- можно ли chain замкнуть на саму себя, чтоб все операции выполнялись в цикле заданное количество раз, либо бесконечно, пока мы насильно не остановим chain?

Добавлено @ 15:08
Sardar, в твоём случае функции выполняются одновременно, а суть chain состоит в том, чтоб выполнять их последовательно, чтоб к примеру сначала выполнилась анимация, после завершения анимации выполнилась логика, после завершения логики вторая анимация и т.п. В этом-то и суть вопроса smile

Это сообщение отредактировал(а) Dr.Zlo - 30.1.2008, 15:19
PM MAIL   Вверх
ksnk
Дата 30.1.2008, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата

 // твой вариант определения чётности был не правильный

Согласен... Зато твой - определение "нечетности", а не "четности" ;-)

Вот такая правка исправит ситуацию... Первым элементом цепочки оказывалась undefined конструкция, которая генерировалась Chain()'ом...
Код

    // main chain function
    x.chain=function(a,b,c){
        if(!a) return this; //<<< 
        if(!(b instanceof Array)) b=[b];
        this.push({a:a,b:b,flag:c});
        return this;
    }






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


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


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

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



Да , еще вот это я поменял
Код

function cur_li(obj){
    var xx= cur_li.next ; 
    $(obj).animate({'fontSize': 40}, 1000, 'linear', function(){
        if (xx) xx();
    })
}


Добавлено через 57 секунд
Хотя, как было - тоже работает ...



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


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


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

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



Обновил листинг функции... теперь в этом примере она еще и прекращать анимацию, в том числе и от jQuery,  умеет корректно...
Код

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=windows-1251">
<script language="javascript" src="jquery.js"></script>
<script>
var CHAIN=Chain(); // <<< Это, чтобы на кнопочку повесить ! :-)

function cur_li(obj){
    $(obj).animate({'fontSize': 40}, 1000, 'linear', function(){
        if (cur_li.next) cur_li.next();
    })
}
function stop_animation(obj_array){
    var i=obj_array.length;
    while(i--){
         $(obj_array.shift()).stop(); // clear all animation напроч!!!
    }
   stop_animation.next();
}

function run_animation(){
    var objs=document.getElementsByTagName('li');
    var x=CHAIN,par=[]; // <<< objs - это не массив...
    for(var i=0; i<objs.length; i++){
        if ( i & 1) { 
            //cur_li(objs[i])
            par.push(objs[i])
            x.chain(cur_li, objs[i]);
        }
    }
    x.chain(stop_animation,[par],'require') // // <<< последний параметр - не важно что, лишь бы был...
    .run();
}

$(run_animation);

</script>
</head>
<body>
<div id='debug' style='float:right;'></div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
</ul>
<input type='button' onclick='run_animation()' value='Run animtion again'>
<input type='button' onclick='CHAIN.clear()' value='Stop animation'>
</body>
</html>



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


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

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



Цитата(Dr.Zlo @  30.1.2008,  13:58 Найти цитируемый пост)
Sardar, в твоём случае функции выполняются одновременно, а суть chain состоит в том, чтоб выполнять их последовательно,

А ты попробуй smile  Функции вызываются в порядке следования, одна закончиться сразу следующая, без паузы.


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Форум для вопросов, которые имеются в справочниках, но их поиск вызвал затруднения, или для разработчика требуется совет или просьба отыскать ошибку. Напоминаем: 1) чётко формулируйте вопрос, 2) приведите пример того, что уже сделано, 3) укажите явно, нужен работающий пример или подсказка о том, где найти информацию.
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: Общие вопросы | Следующая тема »


 




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


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

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