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


99

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

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



6
야,이 질문은 3 년 전의 질문이고 그 안에 훌륭한 답변이 있습니다. 그것을 망칠 필요가 없습니다.
marcio

나는 이것을 검색하고 둘 다 찾았습니다. 당신의 질문은 나이가 많았 기 때문에 두 질문을 하나로 줄이는 것이 좋은 관리라고 생각했습니다. 내 것은 단지 하나의 표입니다. 훨씬 더 많은 사람들이 투표를 닫아야하며 중복 링크가 다른 사람들에게 도움이 될 수 있습니다.
Bernhard Hofmann

2
@Bernard Hofmann이 질문이 더 나은 답을 얻은 경우 중복 질문으로 간주되는지 확실하지 않습니다. 2010 년에 받아 들여진 대답은 "아니오"였습니다.
RoboticRenaissance

답변:


148

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

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

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

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

1
이 부분이 사양의 일부입니까, 아니면 구현에 따라 달라질 수 있습니까?
Tikhon Jelvis

7
1부터 시작하지 않아도됩니다. HTML5 사양에는 "이 호출로 설정할 시간 제한을 식별하는 0보다 큰 사용자 에이전트 정의 정수를 처리하십시오."라고되어 있습니다. 이것은 핸들이 연속적이지 않은 정수와 작은 정수를 포함하는 양의 정수가 될 수있는 공간을 남깁니다.
Mike Samuel

3
그것은 매우 영리하지만 OP는 아마도 활성 타이머를 추적하는 더 나은 솔루션이 있는지 묻습니다.
Jason Harwig

3
무한 루프 아닌가요? 모든 브라우저가 if (0)을 false로 렌더링하는 것은 아닙니다.
Travis J

2
모든 시간 제한을 지우는 방법을 물었으므로이 답변을 수락합니다. 매우 영리한 솔루션입니다.
marcio

79

이 작업을 수행하는 가장 쉬운 방법은 모든 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]);
}

14
이것은 당신이 설정 한 것을 지우는 보너스 (또는 잠재적 인 단점)가 있으므로 실수로 외부 코드를 깨뜨리지 않을 것입니다.
Tikhon Jelvis

1
+1, 모든 시간 제한을 지우지는 않지만 특정 시간 제한 그룹을 한 번에 지우는 좋은 솔루션입니다.
marcio

1
이것은 외부의 암호를 해독하지 않기 때문에 최선의 해결책이다,하지만 난 모든 시간 제한을 삭제하는 방법을 묻는 때부터 :) Pumbaa80 응답 @ 받아들이는 끝났다
마르

2
@marcioAlmada 이상한,하지만 냉각이에 대한 언급을 돌아보기 위해 다시 :) 나중에 2.5yrs
마이클 Berkowski

6
내가 제어하지 않는 웹 페이지에 들어갈 때 모든 시간 제한과 간격을 지우고 싶을 것입니다. 광고 차단기가 실행될 때까지 시작되지 않는 성가신 팝업 광고가 있기 때문입니다.
RoboticRenaissance

12

이전 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);
    };
});

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


더 자세한 정보를 명확히하기위한 하나입니다.
Sanjay

8

타임 아웃 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
    }
};

3

window.setTimeout메서드 를 다시 작성 하고 시간 초과 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();
  }
}

3

모든 시간 제한 을 지우려면 먼저 "캡처"해야합니다 .

다른 스크립트 앞에 아래 코드 를 배치하면 원본 setTimeout&에 대한 래퍼 함수가 생성됩니다 clearTimeout.

모든 (보류중인) 시간 제한을 지울 수 있는 새 clearTimeouts메서드가 windowObject에 추가됩니다 ( Gist 링크 ).

다른 답변 은 가능한 주장에 대한 완전한 지원이 부족 합니다 . setTimeout

// 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, arg ){
    // also, wrap the callback, so the cache reference will be removed 
    // when the timeout has reached (fired the callback)
    var id = _set(function(){
        CB.apply(null, arguments)
        removeCacheItem(id)
    }, duration || 0, arg)

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

    // id reference must be returned to be able to clear it 
    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(){
    console.log("Clearing " + cache.length + " timeouts")
    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);

2

완전성을 위해 setTimeoutsetInterval.

브라우저는 둘 다에 대해 동일한 ID 풀을 사용할 수 있지만 ClearTimeout 및 clearInterval에 대한 답변 중 일부 는 동일합니까? , 동일한 기능 에 의존 clearTimeout하고 clearInterval수행하는 것이 안전한지 또는 각각의 타이머 유형에서만 작업하는 것이 안전한지 여부는 명확하지 않습니다 .

따라서 목표가 모든 시간 제한과 간격을 종료하는 것이라면 모든 구현을 테스트 할 수 없을 때 구현 전반에 걸쳐 약간 더 방어적일 수있는 구현이 있습니다.

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(){}
}

이 기능을 사용하여 현재 창의 모든 타이머를 지울 수 있습니다.

clearAll(window);

또는 다음의 모든 타이머를 지우는 데 사용할 수 있습니다 iframe.

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

이 접근 방식은 vue-cli-service 감시자를 파괴하므로 모든 시간 초과 및 시간 간격을 정리할 때 핫 리로드를 수행 할 수 없습니다. (angular, react, ember 등)과 같은 프레임 워크에 대한 다른 hot reload watcher에서도 동일하다고 가정합니다.
Michail Michailidis

1

Typescript와 함께 Vue를 사용합니다.

    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
        }
    }

0

다른 모든 함수가 타이밍을 파생하는 글로벌 제한 시간을 사용하십시오. 이렇게하면 코드에 추상화가 추가되지만 모든 것이 더 빠르게 실행되고 관리하기 쉽습니다.


나는 당신을 완전히 이해하지 못합니다. set_timeout전역 함수 의 동작을 확장하려고 합니까? 예제 코드를 줄 수 있습니까?
marcio

1
50ms마다 한 번씩 글로벌 타임 아웃이 실행된다는 것을 의미했습니다. 타이밍 요소가 필요한 다른 모든 함수는 글로벌 타임 아웃에서이를 가져옵니다. Google은 효율성을 위해이 기능으로 전환했지만 더 이상 인용 된 기사를 찾을 수 없습니다.
Travis J

0

이 정확한 문제를 해결하는 패키지를 방금 게시했습니다.

npm install time-events-manager

이를 통해 timeoutCollection& intervalCollection개체 를 통해 모든 시간 초과 및 간격을 볼 수 있습니다 . removeAll컬렉션과 브라우저 모두에서 모든 타임 아웃 / 간격을 지우는 기능 도 있습니다 .


0

이것은 매우 늦었지만 ...

기본적으로 setTimeout / setInterval ID는 연속적인 순서로 진행되므로 가장 높은 ID를 얻기 위해 더미 타임 아웃 함수를 만든 다음 그보다 낮은 모든 ID에서 간격을 지 웁니다.

const highestId = window.setTimeout(() => {
  for (let i = highestId; i >= 0; i--) {
    window.clearInterval(i);
  }
}, 0);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.