【发布时间】:2017-04-05 13:31:47
【问题描述】:
编辑:我已将此报告为 Chromium 错误:https://bugs.chromium.org/p/chromium/issues/detail?id=668257
我正在用 JS 创建一个带有可以射击的敌人的小画布游戏。为了测试,我创建了一个标志,全局声明为let fancy = true;,以确定是否使用“花式”定位算法。我这样做是为了按 P 将切换此标志。我的主函数 frame 每秒调用 5 次另一个函数 autoShoot。 autoShoot 使用 fancy 标志。
今天,开始发生一些奇怪的事情;我不记得是什么变化引入了它。有时,当我按下 P 时,autoShoot 的行为就像 fancy 没有被切换。我进行了一些调试,发现新的切换值 反映在 frame 中,但在 autoShoot 中,该值没有更新。它间歇性地发生,有时autoShoot 中的值会自行修复(我没有做任何事情)。
我已将代码简化为以下代码,但对我来说仍然存在问题。尝试按 P 几次。对我来说,这两个值在按 P 一次或两次后“不同步”并显示不同:
(我在 Windows 10 上运行 Chrome“版本 54.0.2840.99 m”。)
const canvas = document.getElementById("c");
const width = 0;
const height = 0;
const ctx = canvas.getContext("2d");
const ratio =1;// (window.devicePixelyRatio||1)/(ctxFOOOOOOOOFOOOOOOOOOFOOOOO||1);
canvas.width = width*ratio;
canvas.height = height*ratio;
canvas.style.width = width+"px";
canvas.style.height = height+"px";
ctx.scale(ratio, ratio);
function testSet(id, val) {
console.log(id+": "+val);
document.getElementById(id).innerText = val;
}
let fancy = true;
document.body.addEventListener("keydown", function(e) {
if (e.keyCode == 80) {
fancy = !fancy;
console.log("Set fancy to: "+fancy);
}
});
let bullets = Array(2000);
let lastTime = 0, shotTimer = 0;
function frame(time) {
const dt = (time - lastTime)/1000;
lastTime = time;
if ((shotTimer -= dt) <= 0) {
testSet("frame", fancy);
autoShoot();
shotTimer = 0.2;
}
for (let b of bullets) {}
requestAnimationFrame(frame);
}
function autoShoot() {
testSet("autoShoot", fancy);
}
requestAnimationFrame(frame);
<code>
fancy (frame) = <span id="frame"></span><br>
fancy (autoShoot) = <span id="autoShoot"></span>
</code>
<canvas id="c"></canvas>
玩玩,这里有一些观察:
- 删除以下任何内容都会导致问题消失:
- 顶部代码中处理画布的任何行,甚至只是
const ratio之后的注释 - 空的 for...of 循环:
for (let b of bullets) {} - 将
let fancy =更改为var fancy =或只是fancy = - 将整个事物置于全局范围之外(通过使用 IIFE、onload 处理程序或块范围)
- 顶部代码中处理画布的任何行,甚至只是
- 增加
bullets数组的大小会增加问题发生的频率。我认为这是因为它使frame执行时间更长;最初,bullets.length只有 20 个,但每次循环迭代都会做一些事情来更新项目符号等。
这是否发生在您的计算机上?这有什么合乎逻辑的解释吗?我试过重启浏览器,没有任何变化。
【问题讨论】:
-
不,在 Firefox 中永远不会不同步
-
在 this fiddle 中对我来说坚如磐石,在 Firefox 和 Chrome 中。
-
我可以复制。
autoShoot需要一些时间来关注更新。很奇怪。 -
@Ultimater 我不再担心让它工作;我刚刚将
let换成了var。现在我只是好奇为什么会发生这种情况。
标签: javascript google-chrome ecmascript-6 requestanimationframe let