setTimeout在事件监听器中不起作用

时间:2018-10-09 07:10:57

标签: javascript settimeout

我一直在做一个简单的程序,它模拟有人在扔东西。一切似乎都正常,但是...我想每100ms执行一次循环。

button.addEventListener("click", function(){

  for(let i = bob_x; i < 1504; i++){
    setTimeout(function(){
      pos_x = i;
      //console.log("vx: " + vx);
      //console.log("vy: " + vy);
      //console.log("i: " + i);
      //console.log("G: " + G);
      pos_y = vy/vx*i - G*i*i/2/vx/vx;

      obj.style.setProperty("left", pos_x);
      obj.style.setProperty("top", parseInt(pos_y, 10));
    }, 100)
  }
})

它不会等待并在大约四分之一秒内执行所有操作。我不知道为什么。

vx和vy是向量的坐标,是通过从事件“ mousedown”的坐标中减去事件侦听器“ mouseup”的坐标而获得的。 Bob_x是代表一个家伙的块的x坐标。

2 个答案:

答案 0 :(得分:2)

  

它不会等待并在大约四分之一秒内执行所有操作。

实际上是十分之一(100ms)。

主要问题是您要安排一堆计时器,这些计时器将在100毫秒后全部关闭。如果您希望它们间隔100毫秒,则需要为后续计时器延长100毫秒的超时时间,例如,将100乘以i - bob_x + 1

button.addEventListener("click", function(){

  for(let i = bob_x; i < 1504; i++){
    setTimeout(function(){
      // ...
    }, 100 * (i - bob_x + 1)) // <============
  }
})

另外,在处理程序中未声明pos_xpos_y似乎很奇怪。

如果这是出于动画目的,则可能要使用requestAnimationFrameHere's an article by Paul Irish可能有用。

答案 1 :(得分:2)

您的for循环正在同步运行,设置了一堆超时,每个超时都将在for循环结束后100毫秒发生。如果要等待每个函数完成再进行下一次迭代,则需要使用不同的策略,也许在每次迭代时使用awaitdelay

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
button.addEventListener("click", async function(){

  for(let i = bob_x; i < 1504; i++){
    await delay(100);
    pos_x = i;
    //console.log("vx: " + vx);
    //console.log("vy: " + vy);
    //console.log("i: " + i);
    //console.log("G: " + G);
    pos_y = vy/vx*i - G*i*i/2/vx/vx;

    obj.style.setProperty("left", pos_x);
    obj.style.setProperty("top", parseInt(pos_y, 10));
  }
})