javascript - лош алгоритъм, задействащ едновременни цикли

Създадох сравнително малък динамичен скрипт за ротация на банери с икони в долната част за поставяне на конкретен банер на фокус. Задействането на mouseenter върху банер спира шоуто на пауза, но понякога, когато изляза с мишката от моя банер, забавянето за определени банери се съкращава. Дори бих разбрал, ако се е случило само веднъж, но забавянето след това се задава за този по-кратък период от време всеки път, когато банерът се връща при ротацията, и често скъсяването се случва на едно друго място в списъка с банери, т.к. добре. Понякога това може да бъде коригирано чрез все още неопределен набор от действия. Започвам да подозирам, че моята логика хваща цикъла някъде по средата и така процесът се разклонява, изпълнява два цикъла, които изглежда ускоряват извикването на функцията 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 вместо забавяне, така че да получите манипулатор на времето за изчакване, което след това можете да отмените, преди да зададете ново време за изчакване (или да отмените, ако възпроизвеждането е настроено на невярно, след това нулирайте, когато възпроизвеждането е отново истина) Това е споменато в JQuery документите за .delay

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

Предполагам, че тъй като не "анулирате" функцията delay()'ed, те се мотаят твърде дълго, но не правят нищо, когато се задействат, защото play е невярно. Но след като играта е true отново, всички започват да имат ефект отново.

Можете да запишете върнатата стойност за delay() и да отмените таймера, като използвате clearTimeout() със стойността.

Въпреки това бих предложил също така да използвате един контейнер за всички банери (и може би да поставите иконите там също) и да зададете mouseenter/mouseleave събитията върху него, а не върху отделни банери. След това има само един елемент, който ще започне/спре въртенето на банера. Ако също така разделите всичко на специфични функции, които възпроизвеждат и спират въртенето, и една за показване на конкретен банер, вероятно можете да получите по-чиста структура на кода.

Ето пример (това е просто нещо, което събрах за забавление, а не редакция на вашия код, така че е съвсем различно. Съжалявам. Но се надяваме, че все още можете да използвате за нещо)

person Flambino    schedule 09.09.2011