如何在ReactJS中简化setTimeout

时间:2019-01-18 09:20:24

标签: javascript reactjs settimeout jsx react-component

纯javaScript中有一个打字动画,该动画已转换为ReactJS。 setTimeout函数看起来不干净,并且没有遵循ReactJS标准的最佳实践。

例如animationManager()

animationManager = () => {
  this.rafRef = requestAnimationFrame(time => {
    const typingData = this.props.data;
    this.typeEffect(time, typingData[this.index], () => {
      this.timeoutRef = setTimeout(() => {
        this.rafRef = requestAnimationFrame(time => {
          this.deleteEffect(time, () => {
            this.timeoutRef = setTimeout(() => {
              this.index =
                this.index === typingData.length - 1 ? 0 : this.index + 1;
              this.animationManager();
            }, this.props.pauseBeforeRestarting);
          });
        });
      }, this.props.pauseBeforeDeleting);
    });
  });
};

是否所有这些setTimout都可以使其变得更加干净?

完整的代码https://codesandbox.io/s/qk4591q1kw

2 个答案:

答案 0 :(得分:1)

是的,您实际上可以创建一个类似于计时器的函数:它会返回一个承诺,该承诺会在时间用尽时得到解决,如下所示:

timer = (duration) => {
  return new Promise(resolve => {
    window.setTimeout(resolve, duration);
  });
}

类似地,您可以对requestAnimationFrame执行相同的操作。诀窍是使用ES6传播运算符,以便您可以将任意数量的参数传递给要调用的回调:

animationFrame = (callback, ...args) => {
  return new Promise(resolve => {
    window.requestAnimationFrame(time => {
      callback(time, ...args);
    });
  })
}

由于您使用的是ES6,因此可以在继续执行下一行代码之前,使用async函数等待计时器完成。如果我们分解您的animationManager()代码,则代码如下:

  1. 您想以typingEffect开头
  2. typingEffect完成后,您想触发deleteEffect

在这种情况下,我们可以这样重构您的代码:

animationManager = () => {
  const deleteFunc = (time, typingData) => {
    this.deleteEffect(time, async () => {
      await this.timer(this.props.pauseBeforeRestarting);
      this.index = this.index === typingData.length - 1 ? 0 : this.index + 1;
      this.animationManager();
    });
  };

  const typeFunc = (time) => {
    const typingData = this.props.data;
    this.typeEffect(time, typingData[this.index], async () => {
      await this.timer(this.props.pauseBeforeDeleting);
      await this.animationFrame(deleteFunc, typingData);
    })
  };

  this.animationFrame(typeFunc);
};

我已分叉您的示例,以提供稍微重构的代码的概念证明:https://codesandbox.io/s/308kxjzwrq

答案 1 :(得分:0)

通常的做法是使用Promises。您可以创建助手Promise,该助手将使用requestAnimationFrame,并通过在onResolve上添加成功回调来使流程平坦且“可设置”。