setTimeout的回调代码运行速度比没有它时要慢得多

Siy*_*mdi 7 javascript performance settimeout reactjs

setTimeout在React上使用Javascript中的函数时,我们正在努力解决一个奇怪的问题。
由于在中使用代码setTimeout,因此运行速度要比不使用代码时运行速度慢得多setTimeout

作为比较,该性能导致:

使用setTimeout1391毫秒,
不使用setTimeout15毫秒

在API回调中(例如axios),也会发生setTimeout版本!


下面显示了一个简单的示例代码:
codesandbox

谁能解释发生了什么事?

import React, { useState } from "react";
import ReactDOM from "react-dom";

function App() {
  const [value, setValue] = useState("");
  const [time, setTime] = useState("");

  const startSample = () => {
    const startTimeStamp = new Date().valueOf();
    for (let i = 0; i < 5000; i++) {
      setValue(`test-${i}`);
      // console.log(`test-${i}`);
    }
    const endTimeStamp = new Date().valueOf();
    setTime(`${endTimeStamp - startTimeStamp}ms`);
  };

  const handleClick1 = () => {
    startSample();
  };

  const handleClick2 = () => {
    setTimeout(() => {
      startSample();
    });
  };

  return (
    <div style={{ textAlign: "left" }}>
      <p>{value || "Please push that button!"}</p>
      <div>
        <button id="startBtn" onClick={handleClick1}>
          Start Normal
        </button>
        <button id="startBtn1" onClick={handleClick2}>
          Start With setTimeout
        </button>
      </div>
      <p>Result: {time}</p>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Run Code Online (Sandbox Code Playgroud)

Bra*_*don 7

React批处理渲染在事件回调中排队,因此setValue一旦处理程序完成,您在click处理程序中对的所有调用都会生成一个渲染。

但是,我不相信React批处理渲染是通过setTimeout调用实现的。因此,它将setValue在setTimeout处理程序中的每次调用后呈现。

看到这个问题:https : //github.com/facebook/react/issues/14259

您应该可以通过这样编写来使setTimeout版本更快:

const handleClick2 = () => {
  setTimeout(() => ReactDOM.unstable_batchedUpdates(() => startSample()));
}
Run Code Online (Sandbox Code Playgroud)

如果您有一堆异步ajax响应返回,并且想要在它们全部到达之后应用它们,那么您可能会有这样的代码:

const [a, setA] = useState();
const [b, setB] = useState();
const [c, setC] = useState();
const [d, setD] = useState();

useEffect(() => {
  (async () => {
    const a = await fetchA();
    const b = await fetchB();
    const c = await fetchC();
    const d = await fetchD();

    // wrap all of the state updates in batchUpdates
    // so that we only get one render instead of 4
    ReactDOM.unstable_batchUpdates(() => {
      setA(a);
      setB(b);
      setC(c);
      setD(d);
    });
  })()
}), []);
Run Code Online (Sandbox Code Playgroud)

  • 在对`ReactDOM.unstable_batchedUpdates`的调用中运行一批状态更新。我将发布一个简短的示例,但是在看不到您的代码的情况下,我不知道它的适用性。 (2认同)