Is it true that, if possible, I should never use setInterval & setTimeout?

I am learning code in JavaScript. I am programming something with some temporary mouse animation. I'm just about to add some code that draws the mouse path.

This will be something that takes a mousemove event, and every time the mice move, draw a new linear path on the Canvas. And over time, this path will become more transparent until it disappears. Of course, new paths will always be opaque, so there is continuous movement.

I figured out the way I can do this with requestanimationframe. Basically every time a new mousemove event occurs, I add the coordinates of the mouse path to an array of objects called mousePathArray. The object will carry the coordinates of the path and the "animationStage" counter. This counter will basically determine how transparent the path will be at this stage of the "animation". (Later steps will be more transparent.)

Then, each animation frame, I will call a function that will loop through all the objects in the array and draw lines according to their coordinates and animationStage counter, increment the counter by 1 and remove the array objects if the animation counter reaches a finite number (which could be 50 or something else).

All of this can be done, but it looks like it would be much easier to do instead of all of this by simply introducing a setInterval function that will be called at a given interval every time the mouse is moved.

So is it worth the long journey? Would it be faster or maybe just better use JS to avoid using setInterval and rAF together?

After writing all this, I wrote the rAF code that I mentioned above. It's too long to put in here, but the rules dictate it. It's on jsfiddle here: http://jsfiddle.net/06f7zefn/2/

(I know there is a lot of inefficiency and probably terrible coding practice, but bear with me, I'm already 5 days old! I can do isDrawing? Boolean instead of calling animate () for each frame, and I can just do ctx.moveTo () once, and the rest is LineTo () without having to moveTo () each iteration, since one point comes from where the other was left)

If I could understand the main idea I'm talking about, this is where I ask for your opinion. Instead of everything related to synchronization arising from the rAF call, would it be better to use setInterval or setTimeout here?

var canvas = document.createElement('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);

var ctx = canvas.getContext('2d');

var currentPosX, currentPosY, prevPosX, prevPosY;
var mousePathArray = [];

canvas.addEventListener ('mousemove', mouseOp);


function mouseOp (mouseEvent) {
    prevPosX = currentPosX;
    prevPosY = currentPosY;
    currentPosX = mouseEvent.clientX;
    currentPosY = mouseEvent.clientY;
    mousePathArray.push( {
        x1: currentPosX,
        x2: prevPosX,
        y1: currentPosY,
        y2: prevPosY,
        animStage: 0
    });
}

function animate () {
    var anims = mousePathArray.length;
    if (anims!=0) {
        for (i=0; i<anims; i++) {
            if (mousePathArray[i].animStage == 20) {
                mousePathArray.splice(i, 1);
                i--;
                anims--;
                continue;
            }

            drawLine(mousePathArray[i].x1, mousePathArray[i].x2, mousePathArray[i].y1, mousePathArray[i].y2, 1 - (mousePathArray[i].animStage * 0.05));
            mousePathArray[i].animStage ++;
        }
    }
}

function drawLine (x1, x2, y1, y2, alpha) {
    ctx.beginPath();
    ctx.moveTo(x1, y1);
    ctx.lineTo(x2, y2);
    ctx.strokeStyle = "rgba(150, 20, 150," + alpha +")";
    ctx.stroke();
}

animloop();

function animloop(){
  window.requestAnimationFrame(animloop);
  gameLoop();
}

function gameLoop() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    animate();
}

      

+3


source to share


3 answers


I don't think using setInterval or setTimeout is bad practice. Using setTimeout is bad practice when you want to do something in the future, but you don't know exactly when you can do it. For example, this is bad practice:

makeHeavyDomMovements();
setTimeout(function () {
  //with 3000 timeout I'm sure any device has made my changes
  makeNextMove();
}, 3000);

      

the right way:

makeHeavyDomMovements().
then(function () {
   makeNextMove();
});

      

If you want to do something in the future since respond to user action 100ms later, it is best to use setTimeout, or if you want to put something on the browser queue, you should use setTimeout (or use a worker if necessary).



This is the same as setInterval, if you are using something that needs to be executed every milliseconds, well you are using it correctly and it is not bad practice, here is a bad use of setInterval:

var dbInterval = setInterval(function () {
  if (dbIsReady()) {
    clearInterval(dbInterval);
    fireReadyEvent();
  }
}, 300);

      

And here is the regular use of setInterval:

setInterval(function () {
  runSync();
}, 600000);

      

Bad practice and good practice are violated by the way you use the environment tools, not the tools themselves.

+7


source


Luz Caballero rightly describes why rAF is a useful replacement for setInterval

:

https://dev.opera.com/articles/better-performance-with-requestanimationframe/ .



As for me, I am now using rAF instead of setInterval, because rAF has some built-in utility that would require additional coding with setInterval:

  • rAF will try to synchronize its calls with the display refresh cycle. This gives the code in a loop the "best chance" to complete between update cycles.

  • If the tasks in cycle # 1 cannot be completed before the request for cycle # 2, then a new cycle # 2 will not be called until incomplete cycle # 1 is completed. This means that the browser will not be overwhelmed with lagging accumulated cycles.

  • If the user switches to another browser tab, then the loops on the current tab are suspended. This allows you to handle the power to switch to a new tab instead of using an invisible tap. It is also a power saving feature on battery powered devices. If you want the loop to continue processing when the tab is not focused, you must use setInterval.

  • The rAF callback function automatically receives a high precision timestamp argument. This allows the rAF beams to compute and use past times. This time can be used to (1) delay until a specified elapsed time occurs, or (2) "catch up" with times that were requested but were not met.

+3


source


the problem is not setTimeout (), but setInterval (), which can lose some executions and has other disadvantages. So always use setTimeout. You have all the details: https://zetafleet.com/blog/2010/04/why-i-consider-setinterval-to-be-harmful.html

0


source







All Articles