最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to overwrite setTimeout before it reach the time set? - Stack Overflow

programmeradmin8浏览0评论

So I'm doing an autoplete search using jquery. I have to set a delay before executing the ajax function because I don't want to hammer my server with calls every time I type on a textbox. Here is my code:

function searchVendor() {
  setTimeout(searchVendor2, 5000);
}

function searchVendor2() {
  var search = $('#inputVendor').val();
  $.ajax({
    type: 'POST',
    url: '/getVendors',
    data: {search: search},
    dataType: 'json',
    success: function(s) {
      $('#inputVendor').autoplete({source: s});
    }
  });
}

so the function searchVendor is executed onkeyup

<input type="text" class="form-control input-sm" id="inputVendor" onkeyup="searchVendor()">

If I type 3 characters (ex. sas) then the function searchVendor2 is executed 3 times. The 5 seconds delay works but it didn't stop and overwrite the previous setTimeout.

What I want to happen is, if I type a character on the textbox it will be executed after 5 seconds, BUT! if a new character is typed before the 5 seconds, setTimeout is reset again to 5 seconds. As long as the user is typing on the textbox the setTimeout is reset to 5 seconds and it will ONLY be executed if the 5 seconds elapsed without the user typing again.

Thanks to those who can help!

So I'm doing an autoplete search using jquery. I have to set a delay before executing the ajax function because I don't want to hammer my server with calls every time I type on a textbox. Here is my code:

function searchVendor() {
  setTimeout(searchVendor2, 5000);
}

function searchVendor2() {
  var search = $('#inputVendor').val();
  $.ajax({
    type: 'POST',
    url: '/getVendors',
    data: {search: search},
    dataType: 'json',
    success: function(s) {
      $('#inputVendor').autoplete({source: s});
    }
  });
}

so the function searchVendor is executed onkeyup

<input type="text" class="form-control input-sm" id="inputVendor" onkeyup="searchVendor()">

If I type 3 characters (ex. sas) then the function searchVendor2 is executed 3 times. The 5 seconds delay works but it didn't stop and overwrite the previous setTimeout.

What I want to happen is, if I type a character on the textbox it will be executed after 5 seconds, BUT! if a new character is typed before the 5 seconds, setTimeout is reset again to 5 seconds. As long as the user is typing on the textbox the setTimeout is reset to 5 seconds and it will ONLY be executed if the 5 seconds elapsed without the user typing again.

Thanks to those who can help!

Share Improve this question edited Jul 28, 2019 at 5:15 MarredCheese 20.8k12 gold badges107 silver badges103 bronze badges asked May 25, 2017 at 5:45 Julio de LeonJulio de Leon 1,2125 gold badges15 silver badges32 bronze badges 2
  • you can give minLength option so that the search will take place only after user enters minimum chars. EG: minLength: 3 – Sravan Commented May 25, 2017 at 5:50
  • I'm not sure of I can say this but doesn't this defeat the autoplete purpose? I think it would be better to use the feature given with the autoplete such min length. – Ossama Commented May 25, 2017 at 7:49
Add a ment  | 

6 Answers 6

Reset to default 9

First, you need to save your timeout id in a global variable, or in a variable that can be accessed later when the function is called again.

Now, whenever your function is called, first you clear that timeout if it exists. Thus you clear any pre-existing timeouts and set a new one every time the function is called.

var myTimeout;

function searchVendor() {
  clearTimeout(myTimeout);
  myTimeout = setTimeout(searchVendor2, 5000);
}

function searchVendor2() {
  var search = $('#inputVendor').val();
  $.ajax({
    type: 'POST',
    url: '/getVendors',
    data: {search: search},
    dataType: 'json',
    success: function(s) {
      $('#inputVendor').autoplete({source: s});
    }
  });
}

The other answers involving setTimeout() are simple and will work, but this is one of the few times when I would remend using a utility library as they can go a few steps further in a way that is noticeable to the user.

It is also important that we avoid re-inventing the wheel. And in this case, what you want is a debounce or throttle function to limit the number of times your handler gets executed within a given time span. The good libraries also accept options to tweak when exactly your handler gets run, which can affect the responsiveness of your app.

Read more about debouncing and throttling.

For your use case, I would remend Lodash's _.throttle() with both leading and trailing options set to true. This will ensure that long entries of text will still get some intermediate results, while also getting results as fast as possible (not having to wait for a timer the first time around) and still guaranteeing that the final keystroke will trigger a new result, which not all debounce settings would do.

const handler = (evt) => {
    console.log('I will talk to the server.');
};

const throttled = _.throttle(handler, 500, {
    leading  : true,
    trailing : true
});

Then register the throttled function as the event listener.

<input type="text" class="form-control input-sm" id="inputVendor" onkeyup="throttled()">

You must clear the timeout when you want to stop it. Instead of just doing this:

var timeoutId;
function searchVendor() {
  timeoutId = setTimeout(searchVendor2, 5000);
}

you should add clearTimeout(timeoutId);, like this:

var timeoutId;
function searchVendor() {
  clearTimeout(timeoutId);
  timeoutId = setTimeout(searchVendor2, 5000);
}

You can use minLength of autoplete so that the API is not called as soon as the user starts typing.

Here is the reference from autoplete

minLength: The minimum number of characters a user must type before a search is performed

$( "#inputVendor" ).autoplete({
  minLength: 3
});

If you want on every keypress, as other answers suggested, you can use clearTimeout to remove the old timeout.

var timeout;

function searchVendor() {
   clearTimeout(timeout);
   timeout = setTimeout(searchVendor2, 5000);
}

The setTimeout and setInterval functions can be stopped using clearTimeout or clearInterval functions, passing the unique identifier generated by the first ones. For example, here you have a small code that helps you to understand this:

var delay;

document.addEventListener("mousemove", function () {
    callSetTimeout();
});

function callSetTimeout () {

    if (!isNaN(delay)) { clearTimeout(delay); }

    delay = setTimeout(function () {
        console.log("do something");
    }, 5000);

}

I change the timeout but I check with interval

var goal={
    cb: cb
,   timeout: (+new Date())+60000 //one minute from now
,   setInterval(function(){
        if((+new Date())>goal.timeout){cb();}
        })
    };

Now I want to increase, decrease or reset the timeout?

goal.timeout-=1000;
goal.timeout+=1000;
goal.timeout=60000;
发布评论

评论列表(0)

  1. 暂无评论