gpt4 book ai didi

javascript - 如何降低 Material UI Slider 因 onChange 触发的 http 请求率?

转载 作者:行者123 更新时间:2023-12-03 08:41:51 27 4
gpt4 key购买 nike

如何缓冲我的请求?

目前我在 React 项目中使用 Material UI 的 slider 。当我沿着 slider 移动时,我使用 onChange 属性触发 http post 请求。代码看起来像这样。

<Slider
onChange={handleChange}
valueLabelFormat={valueLabelFormat}
// aria-labelledby="discrete-slider"
aria-labelledby="non-linear-slider"
valueLabelDisplay="auto"
value={value}
min={1}
max={5}
step={0.05}
/>

但是,如果您可以想象,onChange 将会过于频繁,并且将会发送太多的 HTTP 请求。这绝对不推荐。我也不打算使用 onChangeCommited,因为它不是我想要的交互方式。

这就是我想做的:
如果我沿着 slider (或 onChange)移动,onChange 将不断更新该值,但 http 请求只会每 500 毫秒触发一次(使用 onChange 更新最新值)。而不是每次 onChange 都触发一次请求!
我完全不知道如何实现这个...... setInterval 或......?不太确定。我们将不胜感激。
谢谢!


更新
答案是使用 debounce(请看下面 k.s. 的答案)
然而,我的用例与通常的用例略有不同。我在去抖动中使用的函数需要输入。我在handleChange()函数中使用debounce,因为我需要handleChange来设置 slider 的值(以便它平滑滚动)并在执行http调用的函数上调用debounce。

<Slider
onChange={handleChange}
valueLabelFormat={valueLabelFormat}
// aria-labelledby="discrete-slider"
aria-labelledby="non-linear-slider"
valueLabelDisplay="auto"
value={value}
min={1}
max={5}
step={0.05}
/>

这就是我的handleChange()的样子

const boostedLabel ="some label"

const handleChange = (_event, newValue) => {
//Update value back to Slider
setValue(newValue);

const debouncedFunc = () => updateWeightValue(boostedLabel, newValue);
debounce(debouncedFunc, 300, {leading:false, trailing:true});
};

但是这不起作用! slider 移动,但似乎 debouncedFunc 根本没有被触发。

最佳答案

您的用例与其他去抖动用例没有明显不同,您只是还没有完全理解应该如何使用去抖动。调用 debounce 不会调用您的函数;相反,它返回函数的去抖版本,然后可以使用您需要的任意多个参数正常调用该函数。

您不应在 handleChange 中调用 debounce。您只想在使用它的元素的生命周期内调用它一次 - 然后您在 handleChange 函数中使用该函数的去抖版本(由 debounce 返回)。

最简单的方法是在顶层(完全在组件之外)创建去抖函数。然而,如果页面上可能有多个该类型组件的元素,那么这并不完全安全。如果您有多个元素共享相同的去抖功能,则速度非常快的用户有可能(尽管不太可能)在延迟结束之前(例如 300 毫秒内)更改多个 slider ,在这种情况下,第一个元素更改将没有保存到后端。如果 debounced 函数实际上保存页面上所有可编辑元素的当前状态(而不仅仅是触发更改事件的元素),那么在顶层调用 debounce 就是您想要的。

为了避免顶级反跳的轻微危险,您可以在组件中调用反跳,确保只为元素调用一次。对于下面示例中的第三个 slider ,我在 lazy state initializer 中调用 debounce并忽略 useState 返回的 setter。然后在每次重新渲染时,将使用相同的去抖函数。经过细微的改变,也可以利用 useRef 代替 useStateuseCallbackuseMemo (尽管对于 useCallbackuseMemo 来说,每个元素仅调用一次 debounce 的保证并不安全 - documentation 指出“您可以依赖 useMemo 作为性能优化,而不是作为语义保证。”)。

下面的示例显示了 3 个 slider (全部共享相同的状态)。您可以看到 callHttpRequest 只是将其参数记录到控制台。 3 个 slider 均在其 handleChange 函数中以不同的方式调用此函数。第一个根本没有去抖,因此当您移动 slider 时可以看到许多控制台日志。第二个是在顶层进行去抖的,因此当您停止移动 slider 至少 300 毫秒时,您只能看到控制台日志。第三个是在 lazy initializer 内的组件中去抖的。传递给 useState ,其行为与第二个 slider 相同。

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Grid from "@material-ui/core/Grid";
import Typography from "@material-ui/core/Typography";
import Slider from "@material-ui/core/Slider";
import VolumeDown from "@material-ui/icons/VolumeDown";
import VolumeUp from "@material-ui/icons/VolumeUp";
import debounce from "lodash/debounce";

const useStyles = makeStyles({
root: {
width: 300
}
});

const callHttpRequest = (eventSrcDesc, newValue) => {
console.log({ eventSrcDesc, newValue });
};
const topLevelDebounceCallHttpRequest = debounce(callHttpRequest, 300, {
leading: false,
trailing: true
});

export default function ContinuousSlider() {
const classes = useStyles();
const [value, setValue] = React.useState(30);

const handleChangeNoDebounce = (event, newValue) => {
setValue(newValue);
callHttpRequest("volume-no-debounce", newValue);
};
const handleChangeUsingTopLevelDebounce = (event, newValue) => {
setValue(newValue);
topLevelDebounceCallHttpRequest("volume-top-level", newValue);
};
const [stateDebounceCallHttpRequest] = React.useState(() =>
debounce(callHttpRequest, 300, {
leading: false,
trailing: true
})
);
const handleChangeUsingStateDebounce = (event, newValue) => {
setValue(newValue);
stateDebounceCallHttpRequest("volume-useState", newValue);
};

return (
<div className={classes.root}>
<Typography id="continuous-slider" gutterBottom>
Volume (No Debounce)
</Typography>
<Grid container spacing={2}>
<Grid item>
<VolumeDown />
</Grid>
<Grid item xs>
<Slider
value={value}
onChange={handleChangeNoDebounce}
aria-labelledby="continuous-slider"
/>
</Grid>
<Grid item>
<VolumeUp />
</Grid>
</Grid>
<Typography id="continuous-slider-top-level-debounce" gutterBottom>
Volume (Debounce called at top-level)
</Typography>
<Grid container spacing={2}>
<Grid item>
<VolumeDown />
</Grid>
<Grid item xs>
<Slider
value={value}
onChange={handleChangeUsingTopLevelDebounce}
aria-labelledby="continuous-slider-top-level-debounce"
/>
</Grid>
<Grid item>
<VolumeUp />
</Grid>
</Grid>
<Typography id="continuous-slider-useState-debounce" gutterBottom>
Volume (Debounce called in useState lazy initializer)
</Typography>
<Grid container spacing={2}>
<Grid item>
<VolumeDown />
</Grid>
<Grid item xs>
<Slider
value={value}
onChange={handleChangeUsingStateDebounce}
aria-labelledby="continuous-slider-useState-debounce"
/>
</Grid>
<Grid item>
<VolumeUp />
</Grid>
</Grid>
</div>
);
}

Edit Debounce Slider onChange

这是第二个沙箱,有助于演示顶级去抖与特定于元素的去抖之间的差异:https://codesandbox.io/s/debounce-slider-onchange-jimls?file=/demo.js 。在这个沙箱中,整个组件被渲染两次,延迟为 3 秒而不是 300 毫秒。这提供了充足的时间在延迟结束之前使用顶级去抖来移动两个不同的 slider ,并看到只有第二个 slider 产生控制台日志;而使用特定于元素的去抖函数(通过 useState 管理)对两个 slider 执行相同的操作,会从每个元素生成一个控制台日志。

Lodash 去抖文档:https://lodash.com/docs/4.17.15#debounce

关于javascript - 如何降低 Material UI Slider 因 onChange 触发的 http 请求率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62522994/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com