【问题标题】:Two recursive functions try to execute at the same time when only one should run两个递归函数尝试同时执行,而只有一个函数应该运行
【发布时间】:2017-05-11 08:18:08
【问题描述】:

基本上,我正在尝试创建一个有 2 个按钮的网页;一种会导致屏幕随机闪烁,另一种会导致屏幕缓慢改变颜色。我希望能够在这两者之间切换(如果你按下第一个按钮,它开始闪烁,然后如果你按下第二个按钮,它会慢慢改变,没有任何取消按钮)。

每个按钮都调用一个函数,该函数将另一个函数的“运行”变量设置为 false,并将它自己的“运行”变量设置为 true。然后它调用一个递归函数(递归,它只是一遍又一遍地调用自己)。这些递归函数仅在其“运行”变量为真时执行其代码。

如果您运行 sn-p,您会看到程序非常不一致(您可能需要使用它一段时间才能看到问题,因为它有时似乎可以工作)。有时它拒绝更改功能,有时这两个功能似乎都处于活动状态并且它们都尝试执行(看起来好像它们正在为控制而战)。我不明白这是怎么发生的,因为我相信,任何时候只有一个“运行”变量可以是真的。

var runningDisco = false;
var runningColours = false;


function startColours() {
  if (runningDisco == true); //Is disco running?
  {
    runningDisco = false; //If yes, stop it
  }
  runningColours = true; //Indicate we are running
  window.setTimeout(Colours, 100, 0); //Run
}

function startDisco() {
  if (runningColours == true); {
    runningColours = false;
  }
  runningDisco = true;
  window.setTimeout(Disco, 100);
}

function Disco() {
  if (runningDisco == true); {
    hex = "#";
    for (discoCount = 0; discoCount < 6; discoCount++) {
      hex = hex.concat((Math.floor(Math.random() * 17)).toString(16));
    }
    document.body.style.background = hex;
    window.setTimeout(Disco, 10);
  }

}

function Colours(colourCount) {
  if (runningColours == true); {
    if (colourCount > 359) {
      colourCount -= 359;
    }
    document.body.style.background = "hsl(" + colourCount + ", 50%, 50%)";
    window.setTimeout(Colours, 10, colourCount + 1);
  }

}
input {
  font-family: 'Roboto', sans-serif;
  text-align: center;
  background-color: #dd1021;
  border: none;
  color: white;
  padding: 16px 32px;
  text-decoration: none;
  margin: 4px 2px;
  cursor: pointer;
}
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">

<input id="clickMe" type="button" value="Start Disco" onclick="startDisco();" />
<input id="clickMe" type="button" value="Start Colours" onclick="startColours();" />

【问题讨论】:

  • 我不明白你的标题。这是一个问题还是什么?请让标题更清楚
  • setTimeout 运行相同的函数并不是真正的递归。
  • 是的,这就是为什么我说 递归,因为它只是一遍又一遍地调用自己。不太确定这样的东西的正确名称是什么
  • 也许recurring这个词更合适。

标签: javascript


【解决方案1】:

if 语句后的分号导致问题

例如,替换:

 if (runningColours == true); {
 if (runningDisco == true); {

 if (runningColours == true) {
 if (runningDisco == true) {

Here it is fixed in jsfiddle.

【讨论】:

  • 是的,我似乎在 if 语句中添加并忘记删除它们,然后将 if 语句复制到其他地方
  • 其实,没有。不管有没有分号,结果总是一样的——在此之后runningColours 被设置为false
  • @Bergi 在“开始”函数中是正确的,但在 ColoursDisco 函数中,这就是导致问题的原因
  • 我明白了。但你的回答没有说​​明这一点。
  • 一个问题是。逻辑问题是切换时没有清除间隔
【解决方案2】:
  1. 分号放错了地方
  2. 如果您需要运行单个动画,则需要使用单个全局变量来保存超时处理程序并在开始新的处理程序时将其清除。

像这样:

var running;

function startColours() {
  clearTimeout(running);
  running = setTimeout(Colours, 100, 0); //Run
}

function startDisco() {
  clearTimeout(running);
  running = setTimeout(Disco, 100);
}

function Disco() {
    var hex = "#";
    for (discoCount = 0; discoCount < 6; discoCount++) {
      hex = hex.concat((Math.floor(Math.random() * 17)).toString(16));
    }
    document.body.style.background = hex;
    running = setTimeout(Disco, 10);

}

function Colours(colourCount) {
    if (colourCount > 359) {
      colourCount -= 359;
    }
    document.body.style.background = "hsl(" + colourCount + ", 50%, 50%)";
    running = setTimeout(Colours, 10, colourCount + 1);
}
input {
  font-family: 'Roboto', sans-serif;
  text-align: center;
  background-color: #dd1021;
  border: none;
  color: white;
  padding: 16px 32px;
  text-decoration: none;
  margin: 4px 2px;
  cursor: pointer;
}
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">

<input id="clickMe" type="button" value="Start Disco" onclick="startDisco();" />
<input id="clickMe" type="button" value="Start Colours" onclick="startColours();" />

【讨论】:

  • 这是一个很好的建议,但与 OP 询问的问题无关
  • @SkinnyJ 不是真的。 OP 试图解决的原始问题是“......我希望能够在这两者之间切换”。他的代码是 XY 问题。我为原始问题提供了更好的解决方案。否则这个问题应该被关闭,因为它只是一个错字。
  • @mplungjan 是的。已删除。
【解决方案3】:

真正的问题是DiscoColours 函数中if 语句后面的分号:

if (runningDisco == true); {
  document.body.style.background = …
}

将执行为

if (runningDisco == true)
  ;
{
  document.body.style.background = …
}

无论布尔变量如何,它都会运行内容。为什么有时它会起作用?我猜当两个setTimeout 回调运行得足够近,以至于只有后者被渲染时,感觉是一致的。当然是very unstable - 他们确实在为屏幕时间而战。

【讨论】:

    【解决方案4】:

    对于 JavaScript 新手来说,你犯了一个常见的错误——包括 if 标头后面的分号。这将创建一个没有主体的 if 语句,其后跟一个包含单个语句 runningColours = false 的块,该语句将无法正确执行。下面应该解决这个问题:

    if (runningColours == true)
    {
        runningColours = false;
    }
    

    以下 JSFiddle 链接应该有您的脚本的工作版本: https://jsfiddle.net/4qhmtnhe/ 我希望它开始工作,并且您继续学习 JavaScript。

    【讨论】:

    • if 语句什么都不做,并且总是执行大括号中的代码。
    • 这更多是递归函数、Disco 和 Colours 中的问题,因为这意味着它们会持续运行。
    猜你喜欢
    • 1970-01-01
    • 2017-11-26
    • 1970-01-01
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 2021-02-18
    • 1970-01-01
    相关资源
    最近更新 更多