requestAnimationFrame(callback) 与 for 循环问题
requestAnimationFrame(callback) with for loop issue
最近我发现 JavaScript 的 requestAnimationFrame(callback) 方法有一个奇怪的问题。这是我的代码:
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() 获得预期结果?
window.requestAnimationFrame
是一个异步函数,对于i从0到2,你初始化三个外window.requestAnimationFrame
任务;
经过第3个外window.requestAnimationFrame
任务,i从0变为2,并且flag递增为3;
目前,i 是 2,标志是 3,你在每个内部 window.requestAnimationFrame
回调中都有一个 if 条件 if (flag < 5)
,所以内部回调只有 运行 两次(对于 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);
}
为什么不直接使用 ES6 的 let 来简化这项工作:
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);
}
最近我发现 JavaScript 的 requestAnimationFrame(callback) 方法有一个奇怪的问题。这是我的代码:
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() 获得预期结果?
window.requestAnimationFrame
是一个异步函数,对于i从0到2,你初始化三个外window.requestAnimationFrame
任务;
经过第3个外window.requestAnimationFrame
任务,i从0变为2,并且flag递增为3;
目前,i 是 2,标志是 3,你在每个内部 window.requestAnimationFrame
回调中都有一个 if 条件 if (flag < 5)
,所以内部回调只有 运行 两次(对于 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);
}
为什么不直接使用 ES6 的 let 来简化这项工作:
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);
}