javascript - плохой алгоритм, запускающий параллельные циклы

Я создал относительно небольшой сценарий динамической ротации баннеров с иконками внизу для выделения определенного баннера. Запуск мыши над баннером приостанавливает показ, но иногда, когда я убираю мышь от своего баннера, задержка для определенных баннеров сокращается. Я бы даже понял, если бы это произошло только один раз, но тогда задержка устанавливается на это более короткое время каждый раз, когда баннер возвращается в ротации, и часто сокращение происходит в другом месте в списке баннеров, как Что ж. Иногда это можно исправить еще не определенным набором действий. Я начинаю подозревать, что моя логика ловит цикл где-то посередине, поэтому процесс разветвляется, запускает два цикла, которые, по-видимому, ускоряют вызов функции showNextBanner. Не уверен, как это решить. Я провел тесты, чтобы увидеть, находится ли он в настоящее время в режиме воспроизведения, но безрезультатно.

Я включаю то, что я считаю важными частями кода ниже.

        var firstRun = true;
        var play = true;
        var current = 0;

        var banners = $$( '.banner' ); 
        banners.invoke( 'hide' );
        var images = $$( '.image' );
        var icons = $$( '.icon' );
        //dynamically clones an initial icon to match the number of banners
        initIcons();

        banners.invoke( 'observe', 'mouseenter', function( field ) {
            play = false;
        });

        banners.invoke( 'observe', 'mouseleave', function( field ) {
            if( !play ) {
                play = true;
                showNextBanner().delay(3);
            }
        });

        icons.invoke( 'observe', 'click', function( field ) {
                play = false;
                hideBanner( current );
                showBanner( findObj( icons, field.findElement()));
        });


        showNextBanner().delay(3); 


        function hideBanner( which ) {
            icons[ which ].src = blankIconSRC;
            banners[ which ].hide();
        }


        function showBanner( which ) {
            icons[ which ].src = selectedIconSRC;
            banners[ which ].show();
            current = which;
        }


        // loops the hiding and showing of icons 
        // (mouseenter sets play to false)
        function showNextBanner() {
            if( play ) {
                if( !firstRun ) {
                    if( ++current == banners.length ) current = 0;    
                    var previous = 0;
                    ( current == 0 )? previous = banners.length - 1: previous = current - 1;
                    hideBanner( previous );
                } else {
                    icons[0].src = selectedIconSRC;
                    firstRun = false;
                }
                showBanner( current );
                showNextBanner.delay(3);
            }
        }
    }());

В конце концов, клиенту нужно решение jQuery, чтобы он мог получить эффект слайда, недоступный через scriptaculous. Так что вся эта работа насмарку. Хорошей новостью является то, что я могу просто использовать jCarousel и настроить таблицу стилей. Спасибо за помощь!


person dcoli    schedule 08.09.2011    source источник
comment
showNextBanner ничего не возвращает, поэтому showNextBanner().delay(3), вероятно, вызывает ошибку. Браузеры терпимы к таким вещам, поэтому он может просто продолжаться, однако мне бы не хотелось, чтобы там была эта лишняя задержка.   -  person clockworkgeek    schedule 11.09.2011


Ответы (2)


Я подозреваю, что происходит то, что у вас есть несколько вызовов .delay. Итак, у вас осталось менее 3 секунд, и showNextBanner вызывается снова, устанавливая еще один таймер задержки.

Когда я читаю документы, кажется, что .delay предназначен для создания пробелов в конвейере событий jquery, а не для фактической задержки вызовов функций. Вы можете получить выгоду от переключения на вызов setTimeout вместо задержки, чтобы получить дескриптор тайм-аута, который затем можно отменить перед установкой нового тайм-аута (или отменить, если для воспроизведения установлено значение false, а затем сбросить, когда воспроизведение снова станет истинным) Это упоминается в документах JQuery для .delay.

person jkebinger    schedule 08.09.2011
comment
Ваше подозрение, без сомнения, верно, но на самом деле используется Prototype.js, а не jQuery. Но в обеих библиотеках есть функция delay(), поэтому вам нужны эти документы - person Flambino; 10.09.2011

Я предполагаю, что, поскольку вы не «отменяете» функцию delay(), они зависают слишком долго, но ничего не делают, когда срабатывают, потому что play ложно. Но как только игра снова true, все снова начинает действовать.

Вы можете сохранить возвращенное значение для delay() и отменить таймер, используя clearTimeout() со значением.

Тем не менее, я также предлагаю вам использовать один контейнер для всех баннеров (и, возможно, поместить туда и значки) и установить события mouseenter/mouseleave для него, а не для отдельных баннеров. Тогда есть только один элемент, который запустит/остановит вращение баннера. Если вы также разделите все на определенные функции, которые воспроизводят и останавливают вращение, и одну для отображения определенного баннера, вы можете получить более чистую структуру кода.

Вот пример (это просто то, что я собрал для развлечения, а не для редактирования вашего кода, так что это совсем другое.Извините.Но надеюсь можно еще для чего-то использовать)

person Flambino    schedule 09.09.2011