超越击键:通过调试优化实时建议
#javascript #网络开发人员 #编程 #性能

最近,我有一项更新工作中表单功能的任务。这只是我们曾经看过的常规多步骤。但是,对我而言,有趣的是输入字段之一的行为就像一个组合。因此,当用户在输入字段中键入输入时,将有一个建议框出现在字段下。

Flow chart of a simple Combobox

该概念类似于Instagram的搜索栏。当用户键入搜索栏时,将对后端服务进行API调用,以检索与用户输入最高相似性的用户名的一小部分,然后将其显示给用户。

潜在问题

此功能最直接的方法可能只是创建一个称为handleChange的函数,该函数称为后端服务,然后将其附加到onChange侦听器。对于简单的应用程序,此实现是完美的,并且实现了其目的。但是,对于需要更多计算和巨大数据库需要查询的更复杂的应用程序,此实现最终将给我们带来一些问题。

async function handleChange(e) {
    const users = await callSomeAPI(e.target.value);  // This will take awhile ⌛
    showUserSuggestions(users);
}
<input type="text" onChange="handleChange" />

首先,通过当前实现,我们将在每个键手术中立即一次又一次地调用Handlechange。恭喜,如果该功能内部有一个重量的计算,我们只会阻止主线程并可能冻结UI。没有人喜欢冻结UI。

A simplified state diagram of a text input

最重要的是,我们将对后端进行多个API调用。这将影响后端以及用户网络数据。对我来说,降低数据传输成本也是Web可访问性的一部分。由于它为更多的人打开了使用该功能的访问权限。在我的国家,印度尼西亚,互联网速度在整个群岛各不相同,对于某些人来说,互联网访问的成本也被认为是非常昂贵的。因此,过多的网络请求是值得关注的方面。

那我们该怎么办?

第一个潜在的解决方案之一是仅在达到一定的输入长度时调用函数调用。例如,除非用户键入3个字符或更多字符,否则我们不想开始显示该建议。因此,无论用户类型多次,只要它超过2个字符,都没有网络请求。

async function handleChange(e) {
    if (e.target.value < 3) return;  // Act as a safe guard
    const users = await callSomeAPI(e.target.value);
    showUserSuggestions(users);
}

但是,如果我们考虑一下,这真的没有解决问题,对吗?因为在输入长度超过2个字符之后,它仍然会调用该功能。那么,还有其他选择吗?

介绍调试

Debounce是一种软件机制,可防止频繁调用缓慢的功能。有许多可能的审查应用程序。 Deboune在硬件工程中也是众所周知的,但是我们在这里讨论。

审阅的想法是只有在一定的时间通过而没有任何新功能调用的情况下调用功能。因此,可以说我们要使handleChange使用访问次数,我们设定了以500毫秒的时间进行的时间。这意味着我们可以随意调用handleChange,但是只要函数调用之间的时间差距小于500毫秒,该程序就会忽略所有功能,并且仅在500毫秒之后通过没有任何新功能调用来调用它。

Normal function call timeline

让我们以一个实际的例子来分解过程。想象一个用户输入输入字段,然后将快速输入“ Java”。如果他们停止了小于500毫秒,然后停止键入全秒钟,则称 handleChange 函数被称为一次。此时, e.target.value 的价值将为“ java”。

现在,让我们探索一个场景,在那一秒钟的暂停之后,用户开始键入“ s”,短暂停止了500毫秒,类型为“ c”,再次停止了500毫秒,类型为“ ript”,最后暂停停止打字。在这种情况下, handleChange 函数被调用三次:首先,具有“ s”,然后是“ c”,最后是“ ript”。

Debounced function call timeline

真正的美丽在于其效率。考虑一个长10个字符的单词。与其触发 handleChange 正常情况下的10倍,反驳技术步骤并简化了该过程,仅产生了4个调用。这是一个巨大的胜利!

在JavaScript中实现

现在,我们已经掌握了辩论的概念,让我们使用每个人喜欢的工具:JavaScript!为了实现JavaScript的辩论,我们将利用涉及关闭和 setTimeout 功能的精美技巧。这是您可以烹饪自己的拒绝功能的方法:

function debounce(func, delay) {
  let timeoutId;

  return function (...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => {
      func.apply(this, args);
    }, delay);
  };
}

在此片段中,我们的 debounce 功能具有两个属性: func (您要签发的功能)和 delay (毫秒的时间等待,然后调用拒绝功能)。使用闭合,我们管理 timeoutId ,以便如果用户继续键入,我们可以清除超时。

现在,只需将handleChange传递在debounce中,就像这样:

async function handleChange(e) {
    const users = await callSomeAPI(e.target.value);
    showUserSuggestions(users);
}

const handleChangeDebounced = debounce(handleChange, 500);

图片:当用户疯狂地输入输入字段时,我们的功能保持冷静和收集。只有在暂停500毫秒以上的暂停时,它才会采取行动,以确保我们不会发送不必要的请求并轰炸服务器。我们终于找到了解决我们最初问题的工作解决方案。

包起来

您有了它,将笨拙的文本输入转换为可访问且友好的网络友好的传奇! Debounce只是我们可以选择的众多替代解决方案之一。就像其他任何性能工具一样,我们需要明智地使用它并避免过早优化。

Thumbs up meme gif

这是我在这里写的第一篇博客文章,请给出您的反馈和建议。无论是关于我的写作,插图还是其他任何内容,它都对我来说真的很有价值。希望您能从我的经验中获得一些宝贵的见解!感谢您阅读ð