代码之家  ›  专栏  ›  技术社区  ›  Mo.

如何简化ReactJS中的setTimeout

  •  0
  • Mo.  · 技术社区  · 5 年前

    有一个纯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 回复  |  直到 5 年前
        1
  •  1
  •   Terry    5 年前

    是的,您实际上可以创建类似计时器的函数:它返回一个在时间用完时解析的承诺,如下所示:

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

    requestAnimationFrame . 诀窍是使用ES6 spread运算符,以便可以向要调用的回调传递任意数量的参数:

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

    async 函数等待计时器完成,然后继续执行下一行代码。如果我们把你的 animationManager() 代码,如下所示:

    1. typingEffect
    2. 一次 已完成,您要触发 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

        2
  •  0
  •   Dima Vishnyakov    5 年前

    通常的做法是 Promises 为了这个。通过在resolve上添加成功回调,您可以创建将使用requestAnimationFrame的helper Promise,并使流变得平坦和“可实现”。