如何在每次迭代之间有间隔的循环中为DOM元素设置动画?

Ark*_*kej 6 javascript

我有一个函数foo,我想添加一个睡眠/等待函数来制作一种DOM元素动画.我已经做了一些研究,我知道暂停一个javascript函数是不可能的,因为它会冻结浏览器 - 如果我错了,请纠正我.我怎么能克服它?

function foo() {     
 while (someCondition) {
  var $someDiv = $('.someDiv:nth-child(' + guess + ')');
  $someDiv.css({'background-color': 'red'});
  wait 1000ms
  $someDiv.css({'background-color': 'blue'});
  wait 1000ms
  if (someCondition2) { 
   doSomething; }
  else {
   for loop }
 }
}
Run Code Online (Sandbox Code Playgroud)

$someDiv每个while循环迭代引用不同的DOM元素,因为变量guess变化

我试过的

  • 我使用下面的函数,它工作但问题是我无法for在我的异步函数foo中使用循环

    function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 我试过,setTimeout但我无法取得任何有效的结果.

    如果我将setTimeout这段代码包装起来: ('$someDiv').css({'background-color': 'red'});那么在指定的时间之后,所有的$someDiv'scss样式都会一起改变(请记住,$someDiv每次while循环迭代都会引用不同的DOM元素).

    如果我用setTimeout一个代码包装if,else语句然后我有一个错误 - 无限循环

简化foo功能只是为了可视化问题.我正在处理的原始函数可以在codepen(findNumber函数)上找到

我想制作二进制搜索算法动画.同样的事情也来

我怎样才能达到预期的效果?

一般情况下:如何在循环中为DOM元素设置动画,每次迭代之间有间隔?

lon*_*day 2

解决这个问题的最好、最干净的解决方案是使用未来版本的 Javascript (ES2017) 中的async/await功能。这可以让你摆脱回调地狱。您可以创建一个sleep如下所示的简单函数:

function sleep(time) {
  return new Promise(resolve => setTimeout(()=>resolve(), time));
}
Run Code Online (Sandbox Code Playgroud)

您可以通过正常处理来使用它Promise

sleep(1000).then(()=>console.log('A second later'));
Run Code Online (Sandbox Code Playgroud)

但是,通过该async功能,您可以使用await关键字使代码等待 Promise 解决后再继续。

async function doSomething() {
  await sleep(1000);
  console.log('A second later');
}
Run Code Online (Sandbox Code Playgroud)

这意味着您也可以使用普通循环,包括breakandcontinue语句:

async function doSomething() {
  let i = 0;
  while (true) {
    await sleep(1000);
    console.log(i);
    if (++i === 5) break;
  }
}
Run Code Online (Sandbox Code Playgroud)

这意味着您的代码可以大大简化:

async function foo() {
  var n = 5;
  while (n > 0) {
    n--;
    var wait = 0;
    //$('#someDiv').css({'background-color': 'red'});
    console.log('doSomething-1');
    //wait 1000ms
    await sleep(1000);
    //$('#someDiv').css({'background-color': 'blue'});
    console.log('doSomething-2');

    //wait 1000ms
    await sleep(1000);
    if (true) {
      console.log('doSomething-3');
      break;
    } else {
      console.log('loop')
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

( jsFiddle )

唯一的问题是该功能远未得到普遍支持。因此,您需要使用Babel等软件对其进行转译。

另请注意,在幕后,您的foo函数现在立即返回并给出一个Promise. 这Promise是通过函数的返回值来解决的。因此,如果您想在完成后执行更多代码foo,则必须执行foo().then(/*callback*/).