javascript: Xóa hết thời gian chờ?


99

Có cách nào để xóa mọi lúc mọi nơi khỏi một cửa sổ nhất định không? Tôi cho rằng thời gian chờ được lưu trữ ở đâu đó trong windowđối tượng nhưng không thể xác nhận điều đó.

Mọi giải pháp trình duyệt chéo đều được hoan nghênh.



6
Anh bạn, câu hỏi này là từ 3 năm trước và có câu trả lời tuyệt vời trong đó. Không cần phải gây rối với điều đó.
marcio

Tôi đã tìm kiếm điều này và tìm thấy cả hai. Em đã lớn hơn nên tôi nghĩ sẽ rất tốt nếu giảm hai câu hỏi xuống còn một. Của tôi chỉ là một phiếu bầu; sẽ cần thêm một số người bỏ phiếu để đóng và liên kết trùng lặp có thể giúp ích cho những người khác.
Bernhard Hofmann

2
@Bernard Hofmann Tôi không chắc liệu nó có được tính là một câu hỏi trùng lặp hay không nếu câu hỏi này có câu trả lời tốt hơn. Câu trả lời được chấp nhận cho câu trả lời từ năm 2010 là "Không".
RoboticRenaissance,

Câu trả lời:


148

Chúng không nằm trong đối tượng window, nhưng chúng có id, (afaik) là các số nguyên liên tiếp.

Vì vậy, bạn có thể xóa tất cả thời gian chờ như vậy:

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

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

1
Đây là một phần của thông số kỹ thuật hay nó có thể phụ thuộc vào việc triển khai?
Tikhon Jelvis

7
Nó không cần bắt đầu từ 1. Thông số HTML5 cho biết "Hãy để xử lý là một số nguyên do tác nhân người dùng xác định lớn hơn 0 sẽ xác định thời gian chờ được đặt bởi lệnh gọi này." để lại chỗ cho xử lý là bất kỳ số nguyên dương nào bao gồm các số nguyên không liên tiếp và không nhỏ.
Mike Samuel

3
Điều đó rất thông minh, nhưng OP có lẽ nên hỏi liệu có giải pháp nào tốt hơn để theo dõi bộ hẹn giờ hoạt động hay không.
Jason Harwig

3
Đây không phải là một vòng lặp vô hạn sao? Không phải tất cả các trình duyệt đều hiển thị nếu (0) là false.
Travis J

2
Vì tôi đã hỏi cách xóa TẤT CẢ thời gian chờ, tôi chấp nhận câu trả lời này. Giải pháp rất thông minh.
marcio

79

Tôi nghĩ rằng cách dễ nhất để thực hiện điều này là lưu trữ tất cả các số setTimeoutnhận dạng trong một mảng, nơi bạn có thể dễ dàng lặp lại clearTimeout()trên tất cả chúng.

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
Điều này có phần thưởng (hoặc nhược điểm tiềm ẩn, tôi đoán) là chỉ xóa những cái bạn đặt, vì vậy bạn sẽ không vô tình phá vỡ mã bên ngoài.
Tikhon Jelvis

1
+1, sẽ không xóa tất cả timeout nhưng là một giải pháp tốt để xóa một nhóm cụ thể của timeouts cùng một lúc
Marcio

1
Đây là giải pháp tốt nhất bởi vì nó sẽ không phá vỡ mã bên ngoài, nhưng kể từ khi tôi hỏi làm thế nào để xóa tất cả timeouts tôi đã kết thúc nhận @ Pumbaa80 câu trả lời :)
Marcio

2
@marcioAlmada Strange, nhưng mát mẻ để xem bạn quay lại bình luận về vấn đề này một lần nữa 2.5yrs sau :)
Michael Berkowski

6
Có lẽ tôi muốn xóa tất cả thời gian chờ và khoảng thời gian khi tôi vào một trang web mà tôi không kiểm soát, vì chúng có một quảng cáo bật lên gây phiền nhiễu không bắt đầu cho đến khi trình chặn quảng cáo của tôi chạy.
RoboticRenaissance,

12

Tôi có một bổ sung cho câu trả lời của Pumbaa80 có thể hữu ích cho ai đó đang phát triển cho các IE cũ.

Có, tất cả các trình duyệt chính đều triển khai id thời gian chờ dưới dạng các số nguyên liên tiếp ( không bắt buộc theo đặc tả ). Thông qua số bắt đầu khác nhau giữa trình duyệt biểu mẫu với trình duyệt. Có vẻ như Opera, Safari, Chrome và IE> 8 bắt đầu id thời gian chờ từ 1, các trình duyệt dựa trên Gecko từ 2 và IE <= 8 từ một số ngẫu nhiên được lưu một cách kỳ diệu khi làm mới tab. Bạn có thể tự mình khám phá .

Tất cả những điều đó xảy ra trong IE <= 8, while (lastTimeoutId--)chu kỳ có thể chạy hơn 8 ký tự lần và hiển thị thông báo " Tập lệnh trên trang này khiến Internet Explorer chạy chậm ". Vì vậy, nếu bạn không thể lưu tất cả id thời gian chờ của mình hoặc không muốn ghi đè window.setTimeout, bạn có thể cân nhắc lưu id thời gian chờ đầu tiên trên một trang và xóa thời gian chờ cho đến khi nó.

Thực thi mã khi tải trang đầu:

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

Và sau đó xóa tất cả thời gian chờ đang chờ xử lý có thể do mã nước ngoài đặt nhiều lần bạn muốn


cộng một để làm rõ một số thông tin chi tiết hơn.
Sanjay

8

Làm thế nào về việc lưu trữ các id thời gian chờ trong một mảng toàn cục và xác định một phương thức để ủy quyền lời gọi hàm cho cửa sổ.

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

Bạn phải viết lại window.setTimeoutphương thức và lưu ID thời gian chờ của nó.

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

Để xóa tất cả các timeouts họ phải "bắt" đầu tiên :

Đặt mã dưới đây trước bất kỳ tập lệnh nào khác và nó sẽ tạo ra một hàm bao bọc cho bản gốc setTimeout& clearTimeout.

Một clearTimeoutsphương thức mới sẽ được thêm vào windowĐối tượng, cho phép xóa tất cả thời gian chờ (đang chờ xử lý) ( liên kết Gist ).

Các câu trả lời khác thiếu hỗ trợ đầy đủ cho các lập luận khả thi setTimeoutcó thể nhận được.

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

Để hoàn thiện, tôi muốn đăng một giải pháp chung bao gồm cả setTimeoutsetInterval.

Có vẻ như các trình duyệt có thể sử dụng cùng một nhóm ID cho cả hai, nhưng từ một số câu trả lời cho clearTimeout và clearInterval có giống nhau không? , không rõ liệu có an toàn khi dựa vào clearTimeoutclearIntervalthực hiện cùng một chức năng hay chỉ hoạt động trên các loại hẹn giờ tương ứng của chúng.

Do đó, khi mục tiêu là loại bỏ tất cả thời gian chờ và khoảng thời gian, đây là một triển khai có thể phòng thủ hơn một chút trên các triển khai khi không thể kiểm tra tất cả chúng:

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

Bạn có thể sử dụng nó để xóa tất cả các bộ hẹn giờ trong cửa sổ hiện tại:

clearAll(window);

Hoặc bạn có thể sử dụng nó để xóa tất cả các bộ hẹn giờ trong iframe:

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

hãy nhớ rằng cách tiếp cận này sẽ phá hủy trình theo dõi dịch vụ vue-cli, vì vậy bạn không thể tải lại nóng khi làm sạch tất cả các khoảng thời gian chờ và khoảng thời gian. Tôi cho rằng nó cũng giống như vậy đối với những người theo dõi tải lại nóng khác cho các khuôn khổ như (góc cạnh, phản ứng, ember, v.v.)
Michail Michailidis

1

Tôi sử dụng Vue với 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
        }
    }

0

Sử dụng thời gian chờ chung mà tất cả các chức năng khác của bạn bắt nguồn từ thời gian. Điều này sẽ làm cho mọi thứ chạy nhanh hơn và dễ quản lý hơn, mặc dù nó sẽ thêm một số trừu tượng vào mã của bạn.


Tôi không hoàn toàn hiểu bạn. Ý bạn là để mở rộng hành vi của set_timeouthàm toàn cục? Bạn có thể đưa ra một mã ví dụ?
marcio

1
Ý tôi là bạn có một thời gian chờ toàn cầu chạy một lần sau mỗi 50 mili giây. Mọi hàm khác yêu cầu phần tử định thời sau đó sẽ lấy nó từ thời gian chờ chung. Google đã chuyển sang điều này cho hiệu quả, mặc dù tôi không còn tìm thấy bài báo trích dẫn nó nữa.
Travis J

0

Chúng tôi vừa xuất bản một gói giải quyết vấn đề chính xác này.

npm install time-events-manager

Cùng với đó, bạn có thể xem tất cả thời gian chờ và khoảng thời gian qua timeoutCollection& intervalCollectionđối tượng. Ngoài ra còn có một removeAllchức năng xóa tất cả thời gian chờ / khoảng thời gian khỏi bộ sưu tập và trình duyệt.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.