0

実用的なアプリケーションでwhileループを使用するのはこれが初めてなので、私の無知を許してください。

電球を使用した場合の経時的なコストを示す Web ページを作成しています。

この段階で、while ループを使用して、ユーザーが照明スイッチをクリックしてから経過した時間数を更新して表示しようとしています。(1 時間はリアルタイムの 1 秒を表します)

firebug にブレークポイントを設定すると、while ループ内で setTimeout メソッドに到達するまで、すべて正常に動作します。setTimeout メソッドで中断した後、続行をクリックすると、実際には他に何も実行せずに、すぐに同じ場所で中断します。

ブレークポイントを設定しないと、Firefox がフリーズし、スクリプトの実行を停止する必要があります。

setTimeout を適切に使用していることを再確認しました。何がうまくいかないのかわからないので、どこをチェックすればよいのか、何を検索すればよいのかさえわかりません。私がチェックまたは調査する可能性のあるもののほんのヒントでも、非常に役立ちます.

できるだけ詳細にコードをコメントしようとしました。必要に応じて何かを明確にさせていただきます。

jsfiddle を確認することを強くお勧めします。

JSフィドル

しかし、ここに私のコードがあります:

私のJS

$(document).ready(function () {
    //set image to default off position
    $('#lightswitch').css("background-image", "url(http://www.austinlowery.com/graphics/offswitch.png)");

    // setup the lifetime hours of the lightbulb for later use
    var lifetimeHours = 0;
    // setup function to update the calculated lifetime hours number on the webpage to
    // be called later
    function updateLifetimeHoursHtml (lifetimeHours) {
        $('#lifetimeHours').html(lifetimeHours);
    }
    // set up function to to send to setTimeout
    function updateNumbers () {
        // increment lifetimeHours by one
        lifetimeHours = lifetimeHours++;
        // call function to update the webpage with the new number result
        updateLifetimeHoursHtml(lifetimeHours);
    }

    // When the lightswitch on the webpage is clicked, the user should see the
    // lifetime hours update every second until the user clicks the switch again
    // which will then display the off graphic and pause the updating of the lifetime
    // hours
    $('#lightswitch').click(function(){
        // if the lightswitch is off:
        if ($('#lightswitch').attr('state') == 'off') {
            // set switch to on
            $('#lightswitch').attr('state', 'on');
            // update graphic to reflect state change
            $('#lightswitch').css("background-image", "url(http://austinlowery.com/graphics/onswitch.png)");
            // start updating the lifetime hours number on the webpage
            // while the #lightswitch div is in the on state:
            while ($('#lightswitch').attr('state') == 'on'){
                //call update numbers every second
                setTimeout('updateNumbers()', 1000);
            }
        // the lightswich was not in the off state so it must be on
        }else{
            // change the state of the switch to off
            $('#lightswitch').attr('state', 'off');
            // update graphic to reflect state change
            $('#lightswitch').css("background-image", "url(http://austinlowery.com/graphics/offswitch.png)");
        };
    });
});

私のHTML

<div id="container">
    <div id="lightswitch" state="off">&nbsp;</div>
        <span>After </span><span id="lifetimehours">0</span><span> lifetime hours:</span>
        <br><br>
        <span><b>You have spent:</b></span>
        <br><br>
        <span id="dollaramoutelectricity"></span><span> on electricty</span>
        <br>
        <span id="mainttime"></span><span> on maintenace</span>
        <br>
        <span id="dollaramountbulbs"></span><span> on replacement bulbs</span>
        <br><br>
        <span><b>You have:</b></span>
        <br><br>
        <span>Produced </span><span id="amountgreenhousegasses"></span><span> of greenhouse gasses</span>
        <br>
        <span>Sent </span><span id="amounttrash"></span><span> of trash to the dump</span>
        <br>
        <span>Used </span><span id="amountelectricty"></span><span> of electricity</span>

</div>
4

4 に答える 4

3
var switchTimer;

$('#lightswitch').click(function(){
    if ($('#lightswitch').attr('state') == 'off') {
        $('#lightswitch').attr('state', 'on');
        switchTimer = setInterval(updateNumbers, 1000);
    } else {
        $('#lightswitch').attr('state', 'off');
        $('#lightswitch').css("background-image", "url(http://austinlowery.com/graphics/offswitch.png)");
        clearInterval(switchTimer);
    };

Javascript はイベントベースの言語です。これは、コードが常に実行されるわけではないことを意味します。イベント時のみ運行。while ループを使用することで、基本的にそれを凍結します。JavaScript はそのループ内で常に実行されています。常に何かを実行する必要がある C などの言語では、これで問題ありません。

しかし、それはjavascriptの間違いです。JavaScript の場合、イベントに応答するようにコーディングしてから停止する必要があります。setInterval は常にイベントを生成し、xx ミリ秒ごとに関数を実行します。

タイマーの実行の間にコードは実行されません! これは覚えておくことが重要です。

于 2012-08-29T22:00:05.197 に答える
3

JavaScript はイベント ループを使用します。あなたのループは絶対にwhile生成されないため (無限ループが UI をロックし、ユーザーがそれをオフにできないため、 は永遠に続く)、イベント ループが再び実行されることはなく、登録したコールバックが実行される機会もありません。#lightswitchstateonsetTimeout

本当にやりたいことは、カウンターをsetInterval関数で更新することです。

setInterval(updateNumbers, 1000);
于 2012-08-29T22:00:08.020 に答える
1

イングムの答えに基づいて、

私はそれが次のように良いと思います:

if ($('#lightswitch').attr('state') == 'off') {
    $('#lightswitch').attr('state', 'on');
    $('#lightswitch').css("background-image", "url(http://austinlowery.com/graphics/onswitch.png)");
    updateNumbers();
}

その後

function updateNumbers () {
    lifetimeHours++;
    updateLifetimeHoursHtml(lifetimeHours);
    if($('#lightswitch').attr('state') == 'on'){
        setTimeout(updateNumbers,1000);
    }
}

こちらをご覧ください:http://jsfiddle.net/tdS3A/24/

ただし、最大の精度が必要な場合は、 を格納する必要があります。1 秒のorをnew Date().getTime()実行しても、1 秒ごとに呼び出されることが保証されないためです...setTimeoutsetInterval

function updateNumbers () {
    // call function to update the webpage with the new number result
    updateLifetimeHoursHtml(lifetimeHours+(new Date().getTime()-timerStart)/1000);
    // call updateNumbers() again
    if($('#lightswitch').attr('state') == 'on'){
        timer=setTimeout(updateNumbers,1000);
    }
}
$('#lightswitch').click(function(){
    // if the lightswitch is off:
    if ($('#lightswitch').attr('state') == 'off') {
        // set switch to on
        $('#lightswitch').attr('state', 'on');
        // update graphic to reflect state change
        $('#lightswitch').css("background-image", "url(http://austinlowery.com/graphics/onswitch.png)");
        // update the lifetime hours number on the webpage
        timerStart=new Date().getTime();
        timer=setTimeout(updateNumbers,1000);
        // the lightswich was not in the off state so it must be on
    }else{
        // change the state of the switch to off
        lifetimeHours+=(new Date().getTime()-timerStart)/1000;
        clearTimeout(timer);
        $('#lightswitch').attr('state', 'off');
        // update graphic to reflect state change
        $('#lightswitch').css("background-image", "url(http://austinlowery.com/graphics/offswitch.png)");
    };
});

こちらをご覧ください:http://jsfiddle.net/tdS3A/26/

計算を正確にするために最大の精度の数値が必要な場合でも、ユーザーに表示するときにその値を丸めたい場合があります。次に、使用します

function updateLifetimeHoursHtml (lifetimeHours) {
    $('#lifetimehours').html(Math.round(lifetimeHours));
}
于 2012-08-30T01:07:52.420 に答える
0

通常、setTimeout は setInterval よりも優先されるため、別の解決策は次のとおりです。

変化する

while ($('#lightswitch').attr('state') == 'on'){
    //call update numbers every second
    setTimeout('updateNumbers()', 1000);

setTimeout(function() {  
    updateNumbers();
    if ($('#lightswitch').attr('state') == 'on') 
        setTimeout(arguments.callee, 1000);
    }, 0);

これにより、毎秒ライトスイッチがチェックされ、オフになると停止します。

于 2012-08-29T22:02:01.860 に答える