ปัญหา setTimeout / clearTimeout


103

ฉันพยายามสร้างหน้าเพื่อไปที่หน้าเริ่มต้นหลังจากเช่น ไม่มีการใช้งาน 10 วินาที (ผู้ใช้ไม่ได้คลิกที่ใดก็ได้) ฉันใช้ jQuery สำหรับส่วนที่เหลือ แต่ set / clear ในฟังก์ชันทดสอบของฉันเป็น javascript ล้วน

ในความผิดหวังของฉันฉันจบลงด้วยฟังก์ชั่นบางอย่างเช่นนี้ซึ่งฉันหวังว่าฉันจะสามารถเรียกใช้เมื่อคลิกบนหน้าใดก็ได้ ตัวจับเวลาเริ่มต้นได้ดี แต่ไม่ได้รีเซ็ตเมื่อคลิก หากมีการเรียกใช้ฟังก์ชัน 5 ครั้งภายใน 10 วินาทีแรกการแจ้งเตือน 5 ครั้งจะปรากฏขึ้น ... ไม่ชัดเจนไทม์เอาต์ ...

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

มีใครมีโค้ดบางบรรทัดที่จะทำเคล็ดลับ? - เมื่อคลิกหยุดรีเซ็ตและเริ่มจับเวลา - เมื่อจับเวลาฮิตเช่น 10 วินาทีทำบางสิ่ง

คำตอบ:


226

คุณจำเป็นต้องประกาศtimer นอกฟังก์ชัน มิฉะนั้นคุณจะได้รับตัวแปรใหม่ล่าสุดในการเรียกใช้ฟังก์ชันแต่ละรายการ

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

บวก 1 หนึ่งเพราะจำเป็นในกรณีนี้เพื่อล้างตัวแปรที่บังเวลาออกก่อนที่จะเรียกเวลาออกเพื่อหลีกเลี่ยงไม่ให้เรียกซ้ำสองครั้ง
Diego Favero

46

ปัญหาคือtimerตัวแปรเป็นแบบโลคัลและค่าของมันจะหายไปหลังจากการเรียกใช้ฟังก์ชันแต่ละครั้ง

คุณต้องคงอยู่ต่อไปคุณสามารถวางไว้นอกฟังก์ชันหรือถ้าคุณไม่ต้องการให้ตัวแปรเป็นส่วนกลางคุณสามารถเก็บไว้ในการปิดเช่น:

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

15

นั่นเป็นเพราะตัวจับเวลาเป็นตัวแปรภายในสำหรับฟังก์ชันของคุณ

ลองสร้างมันนอกฟังก์ชัน


6

วิธีใช้สิ่งนี้ในการตอบสนอง:

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

  }
}

มีประโยชน์หากคุณต้องการเรียกใช้ API หลังจากที่ผู้ใช้หยุดพิมพ์เท่านั้น ฟังก์ชัน userTimeout สามารถผูกผ่าน onKeyUp กับอินพุตได้


1
นี่คือสิ่งที่ฉันมองหามาสองสามชั่วโมงแล้วขอบคุณ ฉันแค่สงสัยว่ามีวิธีที่ดีกว่าสำหรับผลลัพธ์แบบนี้หรือไม่?
Nikasv

1
@nikasv throttling และ debouncing เป็นสองทางเลือก: medium.com/@_jh3y/…
zero_cool

2

ไม่แน่ใจว่าสิ่งนี้ละเมิดกฎการเขียนโค้ดแนวปฏิบัติที่ดีหรือไม่ แต่ฉันมักจะออกมาพร้อมกับข้อนี้:

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

ซึ่งจะป้องกันไม่ให้ต้องประกาศตัวจับเวลาออกจากฟังก์ชัน

แก้ไข: สิ่งนี้ไม่ได้ประกาศตัวแปรใหม่ในการเรียกแต่ละครั้ง แต่จะรีไซเคิลเหมือนเดิมเสมอ

หวังว่านี่จะช่วยได้


0

นี้ใช้งานได้ดี เป็นผู้จัดการที่ฉันทำขึ้นเพื่อจัดการกิจกรรมการระงับ มีกิจกรรมสำหรับการระงับและเมื่อคุณปล่อย

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

พารามิเตอร์องค์ประกอบคือพารามิเตอร์ที่คุณถือ พารามิเตอร์ func เริ่มทำงานเมื่อมีค่าเป็นจำนวนมิลลิวินาทีที่ระบุโดยการระงับพารามิเตอร์ พารามิเตอร์ clearfunc เป็นทางเลือกและหากได้รับพารามิเตอร์จะเริ่มทำงานหากผู้ใช้ปล่อยหรือออกจากองค์ประกอบ คุณยังสามารถแก้ไขปัญหาบางอย่างเพื่อให้ได้คุณสมบัติที่คุณต้องการ สนุก! :)


0

ตัวอย่างการใช้งาน Jquery สำหรับเมนูแบบเลื่อนลง! เมื่อวางเมาส์บน #IconLoggedinUxExternal จะแสดง div # ExternalMenuLogin และกำหนดเวลาที่จะซ่อน div # ExternalMenuLogin

เมื่อวางเมาส์บน div # ExternalMenu เข้าสู่ระบบจะยกเลิกการหมดเวลา เมื่อวางเมาส์บน div # ExternalMenuLogin จะตั้งค่าการหมดเวลา

จุดนี้คือการเรียกใช้ clearTimeout ก่อนตั้งค่าการหมดเวลาเสมอเพื่อหลีกเลี่ยงการโทรซ้ำซ้อน

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
    );
});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.