development

javascript : 시간 초과를 모두 지우시겠습니까?

big-blog 2020. 9. 15. 18:54
반응형

javascript : 시간 초과를 모두 지우시겠습니까?


주어진 창에서 모든 시간 초과를 지우는 방법이 있습니까? 시간 초과가 window개체의 어딘가에 저장되어 있다고 가정 하지만 확인할 수 없습니다.

모든 크로스 브라우저 솔루션을 환영합니다.


창 개체에는 없지만 (afaik) 연속 정수인 ID가 있습니다.

따라서 다음과 같이 모든 시간 초과를 지울 수 있습니다.

var id = window.setTimeout(function() {}, 0);

while (id--) {
    window.clearTimeout(id); // will do nothing if no timeout with id is present
}

이 작업을 수행하는 가장 쉬운 방법은 모든 setTimeout식별자를 하나의 배열에 저장 clearTimeout()하는 것입니다. 여기서 모든 식별자를 쉽게 반복 할 수 있습니다 .

var timeouts = [];
timeouts.push(setTimeout(function(){alert(1);}, 200));
timeouts.push(setTimeout(function(){alert(2);}, 300));
timeouts.push(setTimeout(function(){alert(3);}, 400));

for (var i=0; i<timeouts.length; i++) {
  clearTimeout(timeouts[i]);
}

이전 IE를 위해 개발하는 사람에게 유용 할 수있는 Pumbaa80의 답변에 추가되었습니다 .

예, 모든 주요 브라우저는 시간 초과 ID를 연속 정수로 구현 합니다 (사양에 필요하지 않음 ). 시작 번호는 브라우저마다 다릅니다. Opera, Safari, Chrome 및 IE> 8은 탭 새로 고침을 통해 마술처럼 저장되는 임의의 숫자에서 1, 2의 Gecko 기반 브라우저 및 IE <= 8에서 시간 초과 ID를 시작하는 것 같습니다. 직접 발견 할 수 있습니다 .

IE <= 8에서는 while (lastTimeoutId--)주기가 8 자리 이상으로 실행될 수 있으며 " 이 페이지의 스크립트로 인해 Internet Explorer가 느리게 실행 됩니다."라는 메시지가 표시됩니다. 따라서 타임 아웃 ID를 모두 저장할 수 없거나 window.setTimeout재정의 하지 않으려면 페이지의 첫 번째 타임 아웃 ID를 저장하고 그 때까지 타임 아웃을 지우는 것을 고려할 수 있습니다.

초기 페이지로드시 코드 실행 :

var clearAllTimeouts = (function () {
    var noop = function () {},
        firstId = window.setTimeout(noop, 0);
    return function () {
        var lastId = window.setTimeout(noop, 0);
        console.log('Removing', lastId - firstId, 'timeout handlers');
        while (firstId != lastId)
            window.clearTimeout(++firstId);
    };
});

그런 다음 원하는 횟수만큼 외래 코드에 의해 설정되었을 수있는 모든 보류중인 시간 제한을 지 웁니다.


타임 아웃 ID를 전역 배열에 저장하고 함수 호출을 창에 위임하는 메서드를 정의하는 방법은 무엇입니까?

GLOBAL={
    timeouts : [],//global timeout id arrays
    setTimeout : function(code,number){
        this.timeouts.push(setTimeout(code,number));
    },
    clearAllTimeout :function(){
        for (var i=0; i<this.timeouts.length; i++) {
            window.clearTimeout(this.timeouts[i]); // clear all the timeouts
        }
        this.timeouts= [];//empty the id array
    }
};

Without changing any existing code, you can place the below code before anything else, and it will create a wrapper functions for the original setTimeout & clearTimeout and also add a new one clearTimeouts which will clear all the timeouts (Gist link)

// isolated layer wrapper (for the local variables)
(function(_W){

var cache = [],                // will store all timeouts IDs
    _set = _W.setTimeout,      // save original reference
    _clear = _W.clearTimeout;  // save original reference

// Wrap original setTimeout with a function 
_W.setTimeout = function( CB, duration ){
    // also, wrap the callback, so the cache referece will be removed 
    // when the timerout has reached (fired the callback)
    var id = _set(function(){
        CB();
        removeCacheItem(id);
    }, duration || 0);

    cache.push( id ); // store reference in the cache array

    // id must be returned to the user could save it and clear it if they choose to
    return id ;
}

// Wrap original clearTimeout with a function 
_W.clearTimeout = function( id ){
    _clear(id);
    removeCacheItem(id);
}

// Add a custom function named "clearTimeouts" to the "window" object
_W.clearTimeouts = function(){
    cache.forEach(n => _clear(n))
    cache.length = [];
}

// removes a specific id from the cache array 
function removeCacheItem( id ){
    var idx = cache.indexOf(id);

    if( idx > -1 )
        cache = cache.filter(n => n != id )
}

})(window);

You have to rewrite the window.setTimeout method and save its timeout ID.

const timeouts = [];
const originalTimeoutFn = window.setTimeout;

window.setTimeout = function(fun, delay) { //this is over-writing the original method
  const t = originalTimeoutFn(fn, delay);
  timeouts.push(t);
}

function clearTimeouts(){
  while(timeouts.length){
    clearTimeout(timeouts.pop();
  }
}

Use a global timeout which all of your other functions derive timing from. This will make everything run faster, and be easier to manage, although it will add some abstraction to your code.


We've just published a package solving this exact issue.

npm install time-events-manager

With that, you can view all timeouts and intervals via timeoutCollection & intervalCollection objects. There's also a removeAll function which clears all timeouts/intervals both from the collection and the browser.


For completeness, I wanted to post a general solution that covers both setTimeout and setInterval.

It seems browsers might use the same pool of IDs for both, but from some of the answers to Are clearTimeout and clearInterval the same?, it's not clear whether it's safe to rely on clearTimeout and clearInterval performing the same function or only working on their respective timer types.

Therefore, when the goal is to kill all timeouts and intervals, here's an implementation that might be slightly more defensive across implementations when unable to test all of them:

function clearAll(windowObject) {
  var id = Math.max(
    windowObject.setInterval(noop, 1000),
    windowObject.setTimeout(noop, 1000)
  );

  while (id--) {
    windowObject.clearTimeout(id);
    windowObject.clearInterval(id);
  }

  function noop(){}
}

You can use it to clear all timers in the current window:

clearAll(window);

Or you can use it to clear all timers in an iframe:

clearAll(document.querySelector("iframe").contentWindow);

I use Vue with Typescript.

    private setTimeoutN;
    private setTimeoutS = [];

    public myTimeoutStart() {

        this.myTimeoutStop();//stop All my timeouts

        this.setTimeoutN = window.setTimeout( () => {
            console.log('setTimeout');
        }, 2000);

        this.setTimeoutS.push(this.setTimeoutN)//add THIS timeout ID in array

    }

    public myTimeoutStop() {

        if( this.setTimeoutS.length > 0 ) {
            for (let id in this.setTimeoutS) {
                console.log(this.setTimeoutS[id]);
                clearTimeout(this.setTimeoutS[id]);
            }
            this.setTimeoutS = [];//clear IDs array
        }
    }

참고URL : https://stackoverflow.com/questions/8860188/javascript-clear-all-timeouts

반응형