学习这个强大的 JS 特性,可以极大地提高用户体验,阻止用户放弃你的应用。
并大大节省成本。
他们会讨厌你的应用程序
没有它,他们会因为糟糕的用户体验而感到恼火,永远不会回来。
示例:想象一下,已经创建了一个出色的 AI 写作助手,为编写引人入胜的故事提供有用的建议:
图片
已经在 handleChange
中为请求设置好了API:
export function AssistantUI() {
const [suggestions, setSuggestions] = useState('');
const [loading, setLoading] = useState(false);
const handleChange = async (event: any) => {
const value = event.target.value;
setLoading(true);
const res = await fetch(
'https://api.writer.example.com/suggestions',
{
method: 'POST',
body: JSON.stringify({ text: value }),
}
);
const json = await res.json();
setSuggestions(json.suggestions);
setLoading(false);
};
return (
<div className="flex flex-col justify-center flex-wrap content-start">
<textarea
notallow={handleChange}
className="mt-2 mb-4"
cols={40}
rows={10}
/>
{/* ... */}
</div>
);
}
但不幸的是,存在一个严重的问题 - 你能发现吗?👇
图片
我刚开始写作,你的 AI 立刻就在告诉我关于拼写错误的胡说八道!
我的呼吸空间在哪里?你不能至少让我停止打字吗?
哦不,我完了——你毁了我的一天,我永远不会回来😠。
但幸运的是,那只是你在另一个现实中的样子——真正的你已经知道这样的用户体验最好是令人烦恼,最糟糕的是令人愤怒。
这就是为什么你知道这是编写 handleChange
的更好方式:
export function AssistantUI() {
const [suggestions, setSuggestions] = useState('');
const [loading, setLoading] = useState(false);
const timeout = useRef<NodeJS.Timeout | null>(null);
const handleChange = async (event: any) => {
const value = event.target.value;
setLoading(true);
// 重新启动延迟
clearTimeout(timeout.current!);
// 在获取数据前延迟1秒
timeout.current = setTimeout(async () => {
const res = await fetch(
'https://api.writer.example.com/suggestion',
{
method: 'POST',
body: JSON.stringify({ text: value }),
}
);
const json = await res.json();
setSuggestions(json.suggestions);
setLoading(false);
}, 1000);
};
return (
<div className="flex flex-col justify-center flex-wrap content-start">
<textarea
notallow={handleChange}
className="mt-2 mb-4"
cols={40}
rows={10}
/>
{/* ... */}
</div>
);
}
现在 AI 在给出建议前会等待 1 秒!
图片
现在每个人都爱上了你的应用程序 - 即使我们尝试,也无法停止使用它..
在编程中,我们称这种技术为防抖。
它无处不在..
Google 搜索:无论何时搜索,你都在体验防抖动的实际应用。
图片
注意输入和自动完成更新之间的延迟。这不是延迟,而是防抖。
对话:当我们在辩论,你让我先说完我的观点再回应,你就是在防抖。
你没有打断我并开始尖叫——你通过不断设定一个潜意识的超时,确保我最终停止说话:
let silenceTimeout;
let silenceDelay = 1000;
function debounceReplyToOpponent() {
clearTimeout(silenceTimeout);
silenceTimeout = setTimeout(() => {
reply('Your fallacious premises have no basis in reality');
}, silenceDelay);
}
你损失了数千美元
用户不是唯一负载过重的 —— 服务器正在呼救。
在防抖动之前:
1000 个用户每秒打字 10 次 = 10 x 60 x 1000 = 600,000 次请求每分钟!
这个负载并不是云计算的功能问题,但是成本呢?
尤其是因为你可能正在使用像 OpenAI 或 GCP Vertex 这样的昂贵的 AI 服务。
打字频率不再重要 - 如果他们每分钟暂停打字 10 次,那就没关系
10 x 1000 = 10,000 次请求每分钟!请求和成本减少了 98.3%!
之前每天花费 1000 美元,但现在的花费少于 170 美元(!)
你过去花一天的时间,现在需要花一周的时间。这要归功于防抖。
但是你可以做得更好
好吧,但那仍然相当于每月 5000 美元 - 我们能做得更好吗?
用户中有 90%是免费的,我们需要将他们的使用量保持在最低限度。
幸运的是,你非常聪明,所以你很快就想出了这个:
```javascript
const timeout = useRef<NodeJS.Timeout | null>(null);
const ignoring = useRef<boolean>(false);
const handleChange = async (event: any) => {
if (plan === 'free') {
// 仍在忽略,所以返回
if (ignoring.current) return;
// 开始忽略 20 秒
ignoring.current = true;
setTimeout(() => {
ignoring.current = false;
}, 20 * 1000);
}
debounce();
const value = event.target.value;
setLoading(true);
const res = await fetch(
'https://api.writer.example.com/suggestion',
{
method: 'POST',
body: JSON.stringify({ text: value }),
}
);
const json = await res.json();
setSuggestions(json.suggestions);
setLoading(false);
};
在获取他们的最后一个建议后,你将忽略免费用户 20 秒。
所以他们每分钟只有 3 个建议。
900 个免费用户,100 个付费用户。
900 x 3 + 100 x 10 = 3,700 次请求每分钟 - 从降至1,900。
一箭双雕:
- 63%的节省
- 激励免费用户升级以获得无限建议。
这是我们称之为节流的另一种技术。
并且它会出现在你有周期性限制访问某物的任何地方:
- GPT-4o 模型:自 2024 年 5 月 13 日起,仅允许 Plus 用户每 3 小时发送 80 条消息。
- 吃东西:你一次只能吞下那么多食物
我们早些时候辩论的回顾:
- 防抖:你等我说完再回应,反之亦然。
- 节流阀:我们每次最多只有 5 分钟的时间来交谈。
有了这个强大的组合,原本只持续一天的现在可以持续 3 周。
60 万个请求变成了 3700 个,每个人都喜欢你的应用。