【问题标题】:Asynchronous ajax calls in a search box搜索框中的异步 ajax 调用
【发布时间】:2017-09-14 17:37:03
【问题描述】:
几个月前,我为一位客户开发了一个 asp.net 解决方案,我们在其中的输入框中使用 AzureSearch。我的方法是自用户最后一次击键后每秒发送一次 ajax 请求。但是我们的客户希望它总是在输入框发生变化时发生,所以我们这样做了。
这导致客户端报告错误 - 搜索不一致。这是因为竞争条件,我记录了异步调用,这就是发生的事情。我正在考虑为 javascript 自动完成添加 0.5 秒的延迟。或者,还有更好的方法?就像在 javascript 中有一个池。我们使用的控件是 jquery easy autocomplete。
【问题讨论】:
标签:
c#
.net
ajax
asynchronous
race-condition
【解决方案1】:
您正在做的事情称为“去抖动”。去抖动是指当用户开始输入时计时器开始倒计时。如果他们在计时器完成之前输入更多输入,则计时器将重置并再次开始倒计时。只有当计时器完成时,才会进行 AJAX 调用。在这种情况下,研究表明,200 毫秒的延迟是大多数人认为仍能感觉到响应的时间。
但是,如果您真的希望在用户输入时输入结果,那么您需要的就是所谓的“节流”。油门类似于去抖动,除了它定期触发,而不是等待输入停止。但是,要构建一个计时器,您仍然需要一个计时器,您不会在每次用户输入更多输入时重置它。相反,您将使用布尔值来跟踪是否输入了新输入。当计时器完成时,它会检查布尔值是否为真,如果是,则将其设置为假并重新启动计时器倒计时。
您可以通过跟踪 AJAX 调用是否已经发生来改进这两种方法。在这两种情况下,如果计时器用完并且布尔跟踪是否正在进行呼叫为真,则重新启动计时器。
debounce 和 throttle 都已在 lodash 等多个实用程序库中可用。您可以使用它们来包装现有的事件处理程序。
var myInputChangeHandler = function() {
// do ajax call
};
// throttled handler will only be called every 200 ms...
var throttled = _.throttle(myInputChangeHandler, 200);
// ...no matter how many times this event fires
jQuery('input[type=text]').on('change', throttled);
【解决方案2】:
最后我不需要添加延迟或油门。通过查看其官网,我发现 jquery-easy-autocomplete 中有两个非常有用的属性,分别是:
matchResponseProperty:为了避免竞争条件,由于最后一个 ajax 调用不一定是来自后端服务的最后一个响应,它将采用具有此属性指定的属性的最后一个响应,它匹配与输入中的当前文本。
-
listLocation:我试图渲染一个带有匿名项目列表和一个名为 InputPhrase 的属性的 json,直到我遇到了这个问题,所以我在基本响应对象中指定了列表位置,并使用此模型进行响应。
public class SearchViewModel
{
public List<dynamic> Items { get; set; }
public string InputPhrase { get; set; }
}
最后,我将 matchResponseProperty 设置为“InputPhrase”,将 listLocation 设置为“Items”