In Javascript, the execution sequence of a function is executed if the function is already running, but cancel all previously queued

I came across the following script quite often, so I'm wondering if there is a built-in jQuery way to solve the problem.

Provide the following code:

$(document).click(function() { paintCanvas(); }); 

The problem with this code is that if the user clicks on the screen 50 times in a row, you overload the browser with 50 calls of paintCanvas.

If paintCanvas is currently running and a new request is being created, we want to queue a new request so that it waits for paintCanvas to complete. However, at the same time, we can drop any calls that were in the queue for paintCanvas, since we care only about the final state of the mouse, and not about all intermediate states.

Here is the code that solves the problem:

 var _isExecuting, _isQueued; function paintCanvas() { if (_isExecuting) { if (!_isQueued) { _isQueued = true; setTimeout(function() { _isQueued = false; paintCanvas(); }, 150); } return; } _isExecuting = true; // ... code goes here _isExecuting = false; }; 

This AJAX queue plugin essentially implements this functionality, but does so only from an AJAX perspective. Of course, this is a very common problem that can be solved in a more general way?

+4
source share
3 answers

It sounds like you need throttle / debounce features.

There are no built-in methods that I know of from jQuery, you can use any of them:

http://benalman.com/projects/jquery-throttle-debounce-plugin/

http://jsperf.com/jquery-throttle-methods

+2
source

You do not need to solve this problem with mousemove , because the system already does this for you. While paintCanvas is paintCanvas , it does not generate hundreds of mousemove events, even if the mouse moves energetically. Rather, the next event will be the current location of the mouse, and not the queue of all intermediate mouse events.

Take a look at this jsFiddle: http://jsfiddle.net/jfriend00/4ZuMn/ .

Show your mouse around the body (bottom, right panel) as fast as you want. Then remove the mouse from the panel and note that the counter stops immediately - there are no more mouse events. It does not add mouse events ever. Whenever the system is ready for the next mouse event, it receives the last mouse position. Individual mouse movements are NOT queued - they do not accumulate. You can also see in the list of mouse events that many intermediate mouse events are missing (for example, many coordinates are missing), although the mouse went through more positions. This is because the system was not ready to make a mouse event when the mouse was in this position, so the position was skipped.

Also, since javascript is single-threaded, you will never get a new mouse event while you are handling it. The system will not generate a new one until you process the one that you are already alone. This way you will never see _isExecuting as true in javascript in your code. You just don't need this check. And, since you do not need this check, and it will never be true, none of your queue codes will ever be executed. You can see here in this jsFiddle that you can never catch the mousemove event that was re-introduced: http://jsfiddle.net/jfriend00/ngnUT/ . The inAction flag is never perceived to be true, no matter how fast or fast you wiggle the mouse.

+3
source

Although @rkw provided the link, I always prefer to show the code here on SO. Here is some simple code that does what you want. A function that returns a buffered version of another function. This will continue until it stops accepting the event for the given delay . You can configure it if you do not want to wait for a delay after the last event. All you have to do is keep track of when you first set the timeout and estimate subsequent calls to setTimeout .

Here is a working example http://jsfiddle.net/mendesjuan/qfFjZ/

 function createBuffered(handler, delay) { var timeoutId = null; return function() { var me = this; if (timeoutId) { window.clearTimeout(timeoutId); } timeoutId = setTimeout(function() { handle.apply(me, arguments); timeoutId = null; }, delay); } } 
+1
source

Source: https://habr.com/ru/post/1389591/


All Articles