简体   繁体   中英

Can not stop the function running on setTimeout

I have the following javascript function that runs every 10 seconds to sync some data with the database.

function sync(){
  latestID = $("#dataDiv tbody tr:first").attr("data-key");
  var url = '<?=$model['fn']?>';
  $.ajax({
    url: url,
    type: 'post',
    dataType: 'json',
    data:{latestID: latestID},
    success: function (result) {
      //Do some stuff
    }
  });
  setTimeout(sync, 10000);
}

This function starts to execute when a Activate Sync checkbox is checked. but once it is running, it does not stop when unckecking the checkbox. Below is what I already have tried that does do anything and the function gets executing until the page is reloaded (the checkbox is unchecked by default)

function checkSync(){
  var doSync;

  if($('#keepChecking').is(':checked')){
    doSync = sync();
    //alert("checked"); return false;
  }else{
    clearTimeout(doSync);
    return false;
    //alert("not checked"); return false;
  }
}

This should take care of the timeout and of the ajax request:

var ajaxRequest,
    syncTimeout;

function sync(){
  latestID = $("#dataDiv tbody tr:first").attr("data-key");
  var url = '<?=$model['fn']?>';
  ajaxRequest = $.ajax({
    url: url,
    type: 'post',
    dataType: 'json',
    data:{latestID: latestID},
    success: function (result) {
      //Do some stuff
    }
  });
  syncTimeout = setTimeout(sync, 10000);
}

function checkSync(){
  if($('#keepChecking').is(':checked')){
    sync();
    //alert("checked"); return false;
  }else{
    clearTimeout(syncTimeout);
    ajaxRequest.abort();
    return false;
    //alert("not checked"); return false;
  }
}

You didn't attach doSync to the setTimeOut function and declared it within the function, so not globally.

Do the following:

  • Declare var doSync; outside your functions to set it globally.
  • Edit your last line of the function to this: return setTimeout(sync, 10000);

Now doSync will contain the ID value returned by setTimeOut.

Example of a working code:

// Declare the variable globally
var mySync;

function setFunction() {
    // Set mySync to the ID returned by setTimeout (to use clearTimeout)
    mySync = setTimeout(function(){}, 3000);
}

function clearFunction() {
    // Clear timeout with the ID
    clearTimeout(mySync);
}

you need to use some kind of terminator since you are constantly running timeouts.

you could do something like this:

 // let's grab the html elements const counter = document.getElementById('counter'); const start = document.getElementById('start'); const stop = document.getElementById('stop'); // define a counter let count = 0; // function that runs the payload const runTimer = terminator => { counter.textContent = ++count; // on each run assign the new timeout to the terminator object terminator.timeout = setTimeout(()=> runTimer(terminator), 100); }; // define an object we use to access the most recent timeout const terminator = {}; // when i click start → run the payload start.addEventListener('click', e => runTimer(terminator)); // when i click stop → terminate the last created timeout reference. stop.addEventListener('click', e => clearTimeout(terminator.timeout)); 
 <div id="counter">0</div> <br> <button id="start">start</button> <button id="stop">stop</button> 

well.. you don't need to use an object for this but maybe this gives you an idea of how you could create some kind of data binding.

Just as freedomn-m said in the comments of the question, It works fine if I call checkSync function in the setTimeout() .

setTimeout(checkSync, <?=$model['aud'];?>);

The proble was to inform the setTimeout to stop (to call the clearTimeout) which seems like there was a need to run checkSync() regularly so that we could decide if it is needed to call clearTimeout. It now checks if the checkbox state is changed every 10 seconds to decide wether do the sync() or not.

Thank you all for putting your time on this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM