web-dev-qa-db-ja.com

setTimeoutループを停止する方法は?

私は画像スプライトでローディングインジケータを構築しようとしていますが、この関数を思いつきました

function setBgPosition() {
   var c = 0;
    var numbers = [0, -120, -240, -360, -480, -600, -720];
    function run() {
       Ext.get('common-spinner').setStyle('background-position', numbers[c++] + 'px 0px');
        if (c<numbers.length)
        {
            setTimeout(run, 200);
        }else
        {
            setBgPosition();
        }
    }
    setTimeout(run, 200);
}

出力は次のようになります

http://jsfiddle.net/TTkre/

SetBgPosition()を使用する必要がありました。他の内部でこれをループで実行し続けるので、私の問題は[ロード完了]が必要になったらこのループを停止する方法です。

52
Gihan Lasita

setTimeoutは、clearTimeoutでタイムアウトを停止するために使用できるタイマーハンドルを返します。

したがって、たとえば:

function setBgPosition() {
    var c = 0,
        timer = 0;
    var numbers = [0, -120, -240, -360, -480, -600, -720];
    function run() {
        Ext.get('common-spinner').setStyle('background-position', numbers[c++] + 'px 0px');
        if (c >= numbers.length) {
            c = 0;
        }
        timer = setTimeout(run, 200);
    }
    timer = setTimeout(run, 200);

    return stop;

    function stop() {
        if (timer) {
            clearTimeout(timer);
            timer = 0;
        }
}

それを次のように使用します:

var stop = setBgPosition();
// ...later, when you're ready to stop...
stop();

setBgPositionを再度呼び出すのではなく、c0に戻すように設定したことに注意してください。そうでなければ、これは機能しません。また、タイムアウトが保留されていないときのハンドル値として0を使用したことに注意してください。 0setTimeoutからの有効な戻り値ではないため、便利なフラグを作成します。

これは、setIntervalではなくsetTimeoutを使用した方が良いと思う(少数の)場所の1つでもあります。 setIntervalを繰り返します。そう:

function setBgPosition() {
    var c = 0;
    var numbers = [0, -120, -240, -360, -480, -600, -720];
    function run() {
        Ext.get('common-spinner').setStyle('background-position', numbers[c++] + 'px 0px');
        if (c >= numbers.length) {
            c = 0;
        }
    }
    return setInterval(run, 200);
}

このように使用します:

var timer = setBgPosition();
// ...later, when you're ready to stop...
clearInterval(timer);

上記のすべてにもかかわらず、何らかの完了条件が満たされたことを検出することで、setBgPositionが物事を止めるそれ自体にする方法を見つけたいと思います。

84
T.J. Crowder

これは古い質問であることを知っています。とにかく私のアプローチを投稿したいと思います。このように、T。J. Crowderが期限切れにした0のトリックを処理する必要はありません。

var keepGoing = true;

function myLoop() {
    // ... Do something ...

    if(keepGoing) {
        setTimeout(myLoop, 1000);
    }
}

function startLoop() {
    keepGoing = true;
    myLoop();
}

function stopLoop() {
    keepGoing = false;
}
11
ThimoKl

変数を使用して「完了」を追跡し、ループの各反復でテストする必要があります。 done == trueの場合、戻ります。

var done = false;

function setBgPosition() {
    if ( done ) return;
    var c = 0;
    var numbers = [0, -120, -240, -360, -480, -600, -720];
    function run() {
        if ( done ) return;
        Ext.get('common-spinner').setStyle('background-position', numbers[c++] + 'px 0px');
        if (c<numbers.length)
        {
            setTimeout(run, 200);
        }else
        {
            setBgPosition();
        }
    }
    setTimeout(run, 200);
}

setBgPosition(); // start the loop

setTimeout( function(){ done = true; }, 5000 ); // external event to stop loop
2
Neil Essy

タイムアウトループを処理する簡単な方法

function myFunc (terminator = false) {
    if(terminator) {
        clearTimeout(timeOutVar);
    } else {
        // do something
        timeOutVar = setTimeout(function(){myFunc();}, 1000);
    }
}   
myFunc(true); //  -> start loop
myFunc(false); //  -> end loop
2
VALIKHAN

これはextjsタグでタグ付けされているため、extjsメソッドを見る価値があるかもしれません: http://docs.sencha.com/extjs/6.2.0/classic/Ext.Function.html#method-interval

これはsetIntervalとほぼ同じように機能しますが、スコープも考慮し、引数も渡すことができます。

function setBgPosition() {
    var c = 0;
    var numbers = [0, -120, -240, -360, -480, -600, -720];
    function run() {
       Ext.get('common-spinner').setStyle('background-position', numbers[c++] + 'px 0px');
        if (c<numbers.length){
            c=0;
        }
    }
    return Ext.Function.interval(run,200);
}

var bgPositionTimer = setBgPosition();

停止する場合は、clearIntervalを使用して停止できます

clearInterval(bgPositionTimer);

ユースケースの例は次のとおりです。

Ext.Ajax.request({
    url: 'example.json',

    success: function(response, opts) {
        clearInterval(bgPositionTimer);
    },

    failure: function(response, opts) {
        console.log('server-side failure with status code ' + response.status);
        clearInterval(bgPositionTimer);
    }
});
1
Theo

私にはわかりませんが、あなたが望むものかもしれません:

var c = 0;
function setBgPosition()
{
    var numbers = [0, -120, -240, -360, -480, -600, -720];
    function run()
    {
        Ext.get('common-spinner').setStyle('background-position', numbers[c++] + 'px 0px');
        if (c<=numbers.length)
        {
            setTimeout(run, 200);
        }
        else
        {
            Ext.get('common-spinner').setStyle('background-position', numbers[0] + 'px 0px');
        }
    }
    setTimeout(run, 200);
}
setBgPosition();
0
Pritom