Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 防止运行setTimeout的递归函数复合_Javascript_Node.js_Recursion_Browser_Settimeout - Fatal编程技术网

Javascript 防止运行setTimeout的递归函数复合

Javascript 防止运行setTimeout的递归函数复合,javascript,node.js,recursion,browser,settimeout,Javascript,Node.js,Recursion,Browser,Settimeout,我用JavaScript编写了一个Chip-8浏览器,并制作了一个可玩的浏览器版本 它包含一个HTML选择: 庞 俄罗斯方块 每次选择一个ROM时,从文件加载一个ROM: document.querySelector('select')。addEventListener('change',event=>{ 常量rom=event.target.value loadRom(rom) }) 这个loadRom函数获取ROM,将其转换为有用的形式,并将其加载到CPU类的实例中。cpu有一个fet

我用JavaScript编写了一个Chip-8浏览器,并制作了一个可玩的浏览器版本

它包含一个HTML选择:


庞
俄罗斯方块
每次选择一个ROM时,从文件加载一个ROM:

document.querySelector('select')。addEventListener('change',event=>{
常量rom=event.target.value
loadRom(rom)
})
这个
loadRom
函数获取ROM,将其转换为有用的形式,并将其加载到CPU类的实例中。
cpu
有一个fetch-decode-execute循环,该循环通过
step()
调用。我创建了这个
cycle
(main)函数来在setTimeout中调用自己

const loadRom=async rom=>{
const response=wait fetch(`./roms/${rom}`)
const arrayBuffer=wait response.arrayBuffer()
const uint8View=新的Uint8Array(arrayBuffer);
const romBuffer=新的romBuffer(uint8View)
cpu.interface.clearDisplay()
cpu.load(romBuffer)
设定时器=0
异步函数循环(){
计时器++
如果(计时器%5==0){
cpu.tick()
计时器=0
}
等待cpu。步骤()
设置超时(周期,3)
}
循环()
}
这很好,直到我用select加载一个新的ROM。现在,这种循环变得复杂,游戏速度提高了一倍。每次你加载一个新的ROM,它会再次合成并创建一个新的循环


如何创建一个无限循环,但停止它并启动一个全新的循环而不使其复合?

首先,将当前超时设置为一个持久变量,然后在调用
loadRom
之前调用
clearTimeout
。如果还没有加载任何内容,则
clearTimeout
将不会执行任何操作

但是由于您还有
await
s,您需要检查在
await
s运行时是否加载了新的rom。实现这一点的一种方法是使用另一个持久变量,即当前使用的
romBuffer
——如果它与函数闭包中的
romBuffer
不同,则另一个rom已启动,因此立即返回(不要递归创建超时)


尝试使用
setInerval
并跟踪手柄

然后在加载新的(或相同的)rom时清除它


我很尴尬,事情这么简单,我没有想到。非常感谢。一旦它允许我,我会接受答案。从头开始,它似乎是有效的,但如果在改变之前,循环被卡在承诺中,速度将继续增加。哦,好的一点-你可以跟踪当前的
romBuffer
,如果它在
等待期间改变,不要调用
setTimeout
,不幸的是,这并不能解决问题,但问题超出了我的问题范围(我需要取消一个正在运行的承诺),因此我会接受它,因为它对我提出的问题是正确的。
let timeout;
let currentRomBuffer;
const loadRom = async rom => {
  const response = await fetch(`./roms/${rom}`)
  const arrayBuffer = await response.arrayBuffer()
  const uint8View = new Uint8Array(arrayBuffer);
  const romBuffer = new RomBuffer(uint8View)
  currentRomBuffer = romBuffer;
  cpu.interface.clearDisplay()
  cpu.load(romBuffer)

  let timer = 0
  async function cycle() {
    timer++
    if (timer % 5 === 0) {
      cpu.tick()
      timer = 0
    }
    await cpu.step();
    if (romBuffer !== currentRomBuffer) {
      return;
    }
    timeout = setTimeout(cycle, 3);
  }
  cycle()
};
const loadRom = async rom => {
    const response = await fetch(`./roms/${rom}`)
    const arrayBuffer = await response.arrayBuffer()
    const uint8View = new Uint8Array(arrayBuffer);
    const romBuffer = new RomBuffer(uint8View)

    cpu.interface.clearDisplay()
    cpu.load(romBuffer)

    // if rom is loaded, clear it!
    if(this.lastLoad)
        clearInterval(this.lastLoad);

    let timer = 0
    async function cycle() {
        timer++
        if (timer % 5 === 0) cpu.tick()

        await cpu.step()
    }

    // keep track the handle.
    this.lastLoad = setInterval(cycle, 3);
}