javascript - setTimeout 运行其回调代码比没有它慢得多

标签 javascript reactjs performance settimeout

我们在 React 中使用 Javascript 中的 setTimeout 函数时遇到了一个奇怪的问题。
由于使用setTimeout内的代码,它的运行速度比不使用setTimeout的代码慢得多!

作为比较,性能结果为:

Using setTimeout: 1391 ms
without using setTimeout: 15 ms

在 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);

最佳答案

React 批量渲染会在事件回调中排队,因此,一旦处理程序完成,您对点击处理程序中的 setValue 的所有调用都会导致一次渲染。

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

查看此问题:https://github.com/facebook/react/issues/14259

您应该能够通过像这样编写 setTimeout 版本来更快:

const handleClick2 = () => {
  setTimeout(() => ReactDOM.unstable_batchedUpdates(() => startSample()));
}

如果您有一堆异步 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);
    });
  })()
}), []);

关于javascript - setTimeout 运行其回调代码比没有它慢得多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58418160/

相关文章:

javascript - JQuery 数据表对前一列进行排序

javascript - Angular 2.0.0 with angular-cli 1.0.0-beta.15 : using typescript, 如何像以前的版本一样集成外部库

javascript - 如何使用按钮平滑地滚动到网页的不同部分? (最好不要使用 jQuery、Bootstrap 等)

javascript - 从 jquery 模板问题开始

python - 为什么 numpy 的 einsum 比 numpy 的内置函数慢?

javascript - 如何避免 ReactJs 中的 CSS 冲突

java - Mongodb 和 Spring,通过部分名字或姓氏搜索人员的最佳方式

css - React Slick 渲染中的幻灯片溢出

javascript - 有没有更好的方法来对对象数组进行排序以动态生成按值分隔的 HTML 元素?

python - 如何优化python代码(运行时间应小于10s)?