request循环问题的requestAnimationFrame(回调)

时间:2017-08-23 02:06:58

标签: javascript for-loop closures requestanimationframe

最近我发现JavaScript的requestAnimationFrame(回调)方法存在一个奇怪的问题。这是我的代码:

var callback = undefined;
for (var i = 0; i < 3; i++) {
  var flag = 0;
  callback = (function (index) {
    return function () {
      if (flag < 5) {
        flag++;
        console.log('K  i=' + index + ' flag=' + flag);
        window.requestAnimationFrame(callback);
      }
    }
  })(i);
  window.requestAnimationFrame(callback);
}

在我的预期中,应该在控制台中循环如下:

  K  i=0   flag=1
  K  i=0   flag=2
  K  i=0   flag=3
  K  i=0   flag=4
  K  i=0   flag=5
  K  i=1   flag=1
  K  i=1   flag=2
  K  i=1   flag=3
  K  i=1   flag=4
  K  i=1   flag=5
  K  i=2   flag=1
  K  i=2   flag=2
  K  i=2   flag=3
  K  i=2   flag=4
  K  i=2   flag=5

但事实上,控制台日志如下:

K  i=0   flag=1
K  i=1   flag=2
K  i=2   flag=3
K  i=2   flag=4
K  i=2   flag=5

我应该怎么做才能使用for循环和requestAnimationFrame()来获得我的预期结果?

2 个答案:

答案 0 :(得分:0)

window.requestAnimationFrame是一个异步函数,对于i从0到2,你初始化三个外部window.requestAnimationFrame任务;

在前三个外window.requestAnimationFrame任务之后,i从0到2,并且标志增加到3;

目前,i为2,标志为3,每个内部if (flag < 5)回调中都有一个if条件window.requestAnimationFrame,因此内部回调只运行两次(对于flag = 4, flag = 5),i总是2。

我修改了代码:

for (var i = 0; i < 3; i++) {
(function (index) {
    var flag = 0;
    var callback = function () {
        if (flag < 5) {
            flag++;
            console.log('K  i=' + index + ' flag=' + flag);
            window.requestAnimationFrame(callback);
        }
    }
    window.requestAnimationFrame(callback);
})(i);
}

答案 1 :(得分:0)

为什么不使用ES6来让这项工作变得更容易:

for (let i = 0; i < 3; i++) {
	for (let flag = 0; flag < 5; flag++) {
		window.requestAnimationFrame(() => console.log('K  i=' + i + ' flag=' + flag))
  }
}

以上给出了预期的结果。

ES5解决方案

function loop1 (i) {
function loop2 (flag) {
		window.requestAnimationFrame(function () {
			return console.log('K  i=' + i + ' flag=' + flag);
		});
	};

	for (var flag = 0; flag < 5; flag++) {
		loop2(flag);
	}
};

for (var i = 0; i < 3; i++) {
	loop1(i);
}