如果可能的话,我真的不应该使用 setInterval &设置超时? [英] Is it true that if possible I should never use setInterval & setTimeout?

查看:56
本文介绍了如果可能的话,我真的不应该使用 setInterval &设置超时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习用 JavaScript 编写代码.我正在用一些定时鼠标动画来编程.我正要添加一些绘制鼠标路径的代码.

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

这将是一个采用 mousemove 事件的东西,每次鼠标移动时,都会在 Canvas 上绘制一条新的线路径.随着时间的推移,这条路径将变得更加透明,直到它消失.当然,新路径总是不透明的,所以会有持续的运动.

It's going to be something that takes the mousemove event, and every time the mouse moves draw a new line path on Canvas. And with time, that path is going to be more transparent until it disappears. Of course, new paths are always going to be opaque so there's a continuous movement.

我想出了一种方法,只需使用 requestanimationframe 就可以做到这一点.基本上每次发生新的 mousemove 事件时,我都会将该鼠标路径坐标添加到名为 mousePathArray 的对象数组中.该对象将携带路径坐标和animationStage"计数器.该计数器将基本上确定路径在动画"阶段的透明度.(后期将意味着更加透明.)

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

然后每个动画帧我将调用一个函数,该函数将遍历数组中的所有对象并根据它们的坐标和 animationStage 计数器绘制线条,将计数器增加 1,如果 animationStage 计数器将删除数组对象到达结束数字(可能是 50 或其他).

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

这一切都可以完成,但听起来比所有这些都更容易,只需引入一个 setInterval 函数,每次鼠标移动时都会以设定的间隔调用该函数.

This can all be done, but it sounds like instead of all of that, it would be much easier to do by just introducing a setInterval function that will be called with a set interval every time the mouse moves.

那么长途跋涉值得吗?不一起使用 setInterval 和 rAF 会更快还是更好的 JS 实践?

So is it worth it doing the long way? Would it be faster or maybe just be better JS practice to not use setInterval and rAF together?

在写下所有这些之后,我实际上编写了我上面谈到的仅 rAF 代码.粘贴在这里太长了,但规则需要它.这是 jsfiddle:http://jsfiddle.net/06f7zefn/2/

After writing all this down I actually wrote the rAF-only code that I talked about above. It's too long to paste here but the rules need it. Here it is on jsfiddle: http://jsfiddle.net/06f7zefn/2/

(我知道有很多效率低下和可能很糟糕的编码实践,但请耐心等待,我已经 5 天了!我可以制作一个 isDrawing? boolean 而不是在每一帧上调用 animate(),我可以只做 ctx.moveTo() 一次,其余的是 LineTo() 而不必每次迭代 moveTo() 因为一个点起源于另一个离开的地方)

(I'm aware there are a lot of inefficiencies and probably terrible coding practice but bear with me, I'm 5 days old in this! I could make an isDrawing? boolean instead of calling animate() on every frame, and I can just do ctx.moveTo() once with the rest being LineTo() without having to to moveTo() every iteration since one point originates from where the other left off)

如果我能理解我正在谈论的主要想法,那就是我征求您的意见的地方.与其让与计时相关的一切都源自 rAF 调用,不如在这里使用 setInterval 或 setTimeout 更好吗?

If I could get across the main idea I'm talking about, that is where I am asking for your opinion. Instead of making everything related to timing originate from the rAF call could it be better to use setInterval or setTimeout here instead?

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

推荐答案

我不认为使用 setInterval 或 setTimeout 是不好的做法.当您想在将来做某事但您不确切知道何时能够做到这一点时,使用 setTimeout 是一种不好的做法.例如,这是不好的做法:

I don't think using setInterval or setTimeout is bad practice. Using setTimeout is bad practice when you want to do something in future but you don't exactly know when you will be able to do that. For example this is bad practice:

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

正确的方法是:

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

如果你想在未来做一些事情,比如在 100 毫秒后响应用户操作,最好使用 setTimeout 或者如果你想将某些东西放入浏览器队列,你应该使用 setTimeout(或者如果需要,使用一个工作器).

If you want to do something in future like respond to a user action 100ms later, it's best practice to use setTimeout or if you want to put something in browser queue, you should use setTimeout (or use a worker if needed).

它与 setInterval 相同,如果你习惯于做一些应该每 x 毫秒完成一次的事情,那么你正确地使用它并且这不是坏习惯,这是 setInterval 的一个错误用法:

It's the same as setInterval, if you are using to do something that should be done every x milliseconds, well you are using it correctly and it's not bad practice, here is a bad usage of setInterval:

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

这是 setInterval 的常规用法:

And here is a regular usage of setInterval:

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

不好的做法和好的做法取决于您使用环境工具的方式,而不是这些工具本身.

Bad practices and good practices are defied by the way you use your environment tools not those tools themselves.

这篇关于如果可能的话,我真的不应该使用 setInterval &amp;设置超时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆