sự cố setTimeout / clearTimeout


103

Tôi cố gắng tạo một trang để chuyển đến trang bắt đầu sau ví dụ. 10 giây không hoạt động (người dùng không nhấp vào bất kỳ đâu). Tôi sử dụng jQuery cho phần còn lại nhưng set / clear trong hàm thử nghiệm của tôi là javascript thuần túy.

Trong sự thất vọng của tôi, tôi đã kết thúc với một cái gì đó giống như chức năng này mà tôi hy vọng tôi có thể gọi cho bất kỳ nhấp chuột nào trên trang. Bộ hẹn giờ bắt đầu tốt, nhưng không được đặt lại sau một lần nhấp. Nếu hàm được gọi 5 lần trong vòng 10 giây đầu tiên, thì 5 cảnh báo sẽ xuất hiện ... không có clearTimeout ...

function endAndStartTimer() {
    window.clearTimeout(timer);
    var timer;
    //var millisecBeforeRedirect = 10000; 
    timer = window.setTimeout(function(){alert('Hello!');},10000); 
}

Bất kỳ ai có một số dòng mã sẽ thực hiện thủ thuật? - trên bất kỳ điểm dừng nhấp chuột nào, đặt lại và bắt đầu hẹn giờ. - Khi bộ đếm thời gian chạm ví dụ. 10 giây làm gì đó.

Câu trả lời:


226

Bạn cần khai báo timer bên ngoài hàm. Nếu không, bạn sẽ nhận được một biến hoàn toàn mới trên mỗi lần gọi hàm.

var timer;
function endAndStartTimer() {
  window.clearTimeout(timer);
  //var millisecBeforeRedirect = 10000; 
  timer = window.setTimeout(function(){alert('Hello!');},10000); 
}

cộng với 1 vì cần thiết, trong trường hợp này, xóa biến che dấu timeOut trước khi gọi hết thời gian, như vậy, tránh nó được gọi hai lần
Diego Favero

46

Vấn đề là timerbiến là cục bộ và giá trị của nó bị mất sau mỗi lần gọi hàm.

Bạn cần phải duy trì nó, bạn có thể đặt nó bên ngoài hàm hoặc nếu bạn không muốn hiển thị biến dưới dạng toàn cục, bạn có thể lưu trữ nó trong một bao đóng , ví dụ:

var endAndStartTimer = (function () {
  var timer; // variable persisted here
  return function () {
    window.clearTimeout(timer);
    //var millisecBeforeRedirect = 10000; 
    timer = window.setTimeout(function(){alert('Hello!');},10000); 
  };
})();

15

Đó là bởi vì bộ đếm thời gian là một biến cục bộ cho hàm của bạn.

Hãy thử tạo nó bên ngoài chức năng.


6

Một cách để sử dụng điều này trong phản ứng:

class Timeout extends Component {
  constructor(props){
    super(props)

    this.state = {
      timeout: null
    }

  }

  userTimeout(){
    const { timeout } = this.state;
    clearTimeout(timeout);
    this.setState({
      timeout: setTimeout(() => {this.callAPI()}, 250)
    })

  }
}

Rất hữu ích nếu bạn chỉ muốn gọi một API sau khi người dùng đã ngừng nhập. Hàm userTimeout có thể được liên kết qua onKeyUp với một đầu vào.


1
Đây là những gì tôi đã tìm kiếm trong vài giờ, cảm ơn. Tôi chỉ tự hỏi liệu có cách nào tốt hơn để loại kết quả này xảy ra không?
Nikasv

1
@nikasv throttling, và debouncing hai lựa chọn: medium.com/@_jh3y/...
zero_cool

2

Không chắc liệu điều này có vi phạm quy tắc viết mã thực hành tốt nào không nhưng tôi thường đưa ra quy tắc này:

if(typeof __t == 'undefined')
        __t = 0;
clearTimeout(__t);
__t = setTimeout(callback, 1000);

Điều này ngăn chặn sự cần thiết phải khai báo bộ đếm thời gian ngoài chức năng.

CHỈNH SỬA: điều này cũng không khai báo một biến mới ở mỗi lần gọi, nhưng luôn luôn tái chế giống nhau.

Hi vọng điêu nay co ich.


0

Điều này hoạt động tốt. Đó là một người quản lý tôi đã thực hiện để xử lý các sự kiện tổ chức. Có các sự kiện để giữ và khi bạn buông bỏ.

function onUserHold(element, func, hold, clearfunc) {
    //var holdTime = 0;
    var holdTimeout;

    element.addEventListener('mousedown', function(e) {
        holdTimeout = setTimeout(function() {
            func();
            clearTimeout(holdTimeout);
            holdTime = 0;
        }, hold);
        //alert('UU');
    });

    element.addEventListener('mouseup', clearTime);
    element.addEventListener('mouseout', clearTime);

    function clearTime() {
        clearTimeout(holdTimeout);
        holdTime = 0;
        if(clearfunc) {
            clearfunc();
        }
    }
}

Tham số phần tử là tham số mà bạn nắm giữ. Thông số func kích hoạt khi nó giữ trong một số mili giây được chỉ định bởi thông số giữ. Tham số clearfunc là tùy chọn và nếu nó được cung cấp, nó sẽ bị kích hoạt nếu người dùng bỏ qua hoặc rời khỏi phần tử. Bạn cũng có thể thực hiện một số giải pháp thay thế để có được các tính năng bạn muốn. Thưởng thức! :)


0

Ví dụ thực tế Sử dụng Jquery cho menu thả xuống! Khi di chuột qua #IconLoggedinUxExternal hiển thị div # ExternalMenuLogin và đặt thời gian chờ để ẩn div # ExternalMenuLogin

Khi di chuột qua div # ExternalMenuLogin, nó sẽ hủy thời gian chờ. Khi di chuột ra div # ExternalMenuLogin, nó sẽ đặt thời gian chờ.

Vấn đề ở đây là luôn gọi clearTimeout trước khi đặt thời gian chờ, vì vậy, tránh các cuộc gọi kép

var ExternalMenuLoginTO;
$('#IconLoggedinUxExternal').on('mouseover mouseenter', function () {

    clearTimeout( ExternalMenuLoginTO )
    $("#ExternalMenuLogin").show()
});

$('#IconLoggedinUxExternal').on('mouseleave mouseout', function () {

    clearTimeout( ExternalMenuLoginTO )    
    ExternalMenuLoginTO = setTimeout(
        function () {

            $("#ExternalMenuLogin").hide()

        }
        ,1000
    );
    $("#ExternalMenuLogin").show()
});

$('#ExternalMenuLogin').on('mouseover mouseenter', function () {

    clearTimeout( ExternalMenuLoginTO )
});
$('#ExternalMenuLogin').on('mouseleave mouseout', function () {

    clearTimeout( ExternalMenuLoginTO )
    ExternalMenuLoginTO = setTimeout(
        function () {

            $("#ExternalMenuLogin").hide()

        }
        ,500
    );
});
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.