1

編集: ここに投稿した元の YUI3 の質問に対する答えを見つけましたが、別の質問につながったので、新しいスレッドを開始する代わりに、ここに追加するだけだと思いました。下にスクロールして新しい質問を見つけてください (太字になっています)。

元の質問: YUI 定義内で JavaScript カウントダウン タイマーを作成する際に問題が発生しています。私の推測では、オブジェクトのスコープに関係しています。これが私のコードです:

YUI({combine: true, timeout: 10000}).use("node", function (Y) {
    var timer = new function(){};
    Y.augment(timer, Y.EventTarget);
    timer.on('timer:down', function() {
        Y.log('timer down event fired', 'event');
        Y.Lang.later(1000, Y, timer_trigger());
    });
    timer.on('timer:end', function() {
        Y.log('timer end event fired', 'event');
    });

    var timer_from;

    function startTimer(seconds){ // start a coundown from seconds to 0
        timer_from = seconds;
        timer_trigger();
    }

    function timer_display(){
        var mins = Math.floor(timer_from/60);
        var secs = timer_from - mins*60;
        var secsDisp = secs;
        if(secs<10){
            secsDisp = '0' + secs;
        }
        Y.one('#timer').set('innerHTML', mins + ':' + secsDisp);
    }

    function timer_trigger(){
        Y.log('timer from is: '+timer_from);
        if(timer_from > 0){
            timer_from--;
            timer_display();
            if(timer_from > 0){
                timer.fire('timer:down');
            }
        } else {
            timer.fire('timer:end');
        }
    }

    function initializePage(){
        startTimer(900);
    }


});

私が得ているエラーは、呼び出しを要求しているように 1000 ミリ秒待たず、timer_trigger()最終的に Safari がコードの実行を停止するかどうかを尋ねてくることです。ページを読み込んでから数秒すると、タイマーはすでに約 3、4 分になっています。も使用してみましsetTimeoutたが、同じ結果が得られます。誰でも助けることができますか?とても感謝しております!

編集:私は実際に解決策を見つけました-これは何時間も試行錯誤した結果ですが、さらにいくつかのGoogle検索で新しい結果/回答が得られる場合があります(実際、このサイトで回答を見つけました)。

どうやら私のコードが競合状態を作成していたようで、それを修正するために私がしなければならなかったのはこれだけです:

setTimeout(function(){ 
    timer_trigger();
}, 1000);

私は競合状態を調べましたが、それが私の場合に何を意味するのか、そして私のコードへの一見些細な変更が私が抱えていた問題をどのように修正したのかは不明です。元の質問は答えましたが、これを答えから生じた質問に変えたいと思います。

JavaScript のスレッド化はどのように機能し、競合状態の原因は何ですか?コードの小さな変更によってエラーが修正されたのはなぜですか?

4

2 に答える 2

3

問題は競合状態ではありません。setTimeout への追加の呼び出しがコードを「修正」する理由は、timer_trigger. timer_from関数が呼び出されたときに が 1の場合に何が起こるかを考えてみましょう。timer:down も timer:end もトリガーされません。

function timer_trigger(){
    Y.log('timer from is: '+timer_from);
    if(timer_from > 0){      // Since timer_from is 1, the if block is entered
        timer_from--;        // timer_from is 0
        timer_display();
        if(timer_from > 0){  // This block is not entered, but it has no matching else
            timer.fire('timer:down');
        }
    } else {                 // The matching if block was entered, so this is not
        timer.fire('timer:end');
    }
}

このコードを追加しました:

setTimeout(function(){ 
    timer_trigger();
}, 1000);

これにより、すでに 0 に設定されているtimer_triggerがもう一度呼び出されtimer_from、else ブロックを実行できるようになります。

于 2009-12-04T15:05:16.223 に答える
2

また、

Y.Lang.later(1000, Y, timer_trigger());

timer_trigger をすぐに実行し、戻り値を Y.Lang.later に渡します。あなたはおそらく意味した

Y.Lang.later(1000, Y, timer_trigger);
于 2009-12-04T20:36:36.837 に答える