【问题标题】:How do I pause and call a function inside a nested for loop?如何在嵌套的 for 循环中暂停和调用函数?
【发布时间】:2019-06-11 17:30:29
【问题描述】:

我正在尝试帮助想要在网页上显示一组随机生成的颜色的排序的学生。他有一个用随机生成的 HSL 颜色填充全局数组的函数:

function shuffle(array)
{
  for(i=array.length-1;i>0;i--)
  {
    var random = Math.floor(Math.random() * (i+1));
    var temp = array[i];
    array[i] = array[random];
    array[random] = temp;
  }
}

还有另一个函数,它在 HTML 画布上显示一系列从左到右的数组中颜色的细垂直矩形:

function draw()
{ 
  for(d=0;d<361;d++)
  {
    hue = cArray[d].slice(4,cArray[d].indexOf(",", 4));
    ctx.fillStyle = `hsl(`+ hue + `,100%,50%)`;
    ctx.fillRect(x,0,4,canvas.height);
    x=x+3;
  }
  x=0; //reset x-coordinate
}

然后是一个包含冒泡排序算法的函数:

function bubbleSort(array)
{
  for(i=0;i<array.length;i++)
  {
    for(j=1;j<array.length;j++)
    {
      var hue1 = array[j-1].slice(4,array[j-1].indexOf(","));
      var hue2 = array[j].slice(4,array[j].indexOf(","));
      if(Number(hue1) > Number(hue2))
      {
        var temp = array[j-1];
        array[j-1] = array[j];
        array[j] = temp;
        // webpage hangs if function call put here
      }
    }
  }
  // webpage works if function call put here
}

如果 draw() 函数调用在嵌套循环内,则网页挂起。但如果 draw() 函数调用是在循环之后,排序完成,学生只能看到最终排序的数组。我们如何暂停循环并每隔一段时间调用draw()函数,以便排序算法显示该过程?

我查看了很多讨论论坛,它们提出了异步和递归解决方案(我只能理解一些),但它们似乎从未适用于嵌套循环。有什么想法吗?

【问题讨论】:

    标签: javascript function loops nested call


    【解决方案1】:

    最简单的方法是创建函数async(一个 ES2017 的东西,如果你必须针对旧环境,你可以转换它)。然后,您可以await 一个延迟,允许浏览器重新绘制画布。使用 async 函数可以让您继续编写循环而不是异步回调,同时仍然获得在画布上显示内容所需的异步行为。

    这是一个更简单的例子:

    const outer = document.getElementById("outer");
    const inner = document.getElementById("inner");
    
    function delay(ms) {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve();
            }, ms);
        });
    }
    
    async function example() {
        for (let i = 0; i < 4; ++i) {
          outer.textContent = String(i);
          outer.className = "cls" + (i % 4);
          for (let j = 0; j < 4; ++j) {
              inner.textContent = String(j);
              inner.className = "cls" + (j % 4);
              await delay(200);
          }
        }
    }
    
    example()
    .catch(error => {
        console.error(error);
    });
    .cls0 {
      color: blue;
    }
    .cls1 {
      color: red;
    }
    .cls2 {
      color: green;
    }
    .cls3 {
      color: black;
    }
    <div id="outer"></div>
    <div id="inner"></div>

    问题中的代码正在成为我所说的(在我贫血的小博客上)The Horror of Implicit Globals 的牺牲品。您的学生需要声明这些循环计数器。

    【讨论】:

    • 太棒了!谢谢!我真的不明白异步函数是如何工作的或等待/承诺/解决结构是如何工作的(我将不得不做更多的阅读),但我得到了它的工作。我读过一些论坛,建议(就像你一样)使用'let'声明循环计数器,但我学生的代码似乎没有它也能工作。 'let' 关键字与普通的 'var' 有何不同?
    • @DerekP - 学生的代码甚至没有使用var,请参阅上面的“恐怖”链接。但是let和var之间的区别:stackoverflow.com/questions/4862193/…
    猜你喜欢
    • 1970-01-01
    • 2013-09-01
    • 1970-01-01
    • 2020-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    相关资源
    最近更新 更多