jquery:基于ajax的搜索 – 浏览器崩溃?

嘿伙计们,我正在研究一个相当奇怪的基于ajax的搜索模型。 搜索实际上并不是从服务器检索真实的搜索结果,而是加载网站的站点地图(使用jquery load()方法)并提取其链接。

这实际上非常好,但有一个小错误可能导致我的浏览器崩溃。

var searchTimer = 0; $('.s').keyup(function(e) { switch (e.keyCode) { //case 8: // Backspace case 9: // Tab case 13: // Enter doSearch(e.keyCode); break; case 16: // Shift ... case 37: // Left break; case 38: // Up doSearch(e.keyCode); break; case 39: // Right break; case 40: // Down doSearch(e.keyCode); break; ... break; default: if (searchTimer != 0) { clearTimeout(searchTimer); } searchTimer = setTimeout(function () { doSearch(e.keyCode); }, 250); } }); function doSearch(keyCode) { if ($('.s').val() != '') { searchTimer = 0; $sr.load('/sitemap/', function() { }); // end load } else { clearsearch(true); } } 

我遇到的唯一问题是,一旦我在.s输入字段中输入一个单词并且在250ms内立即删除它,网站就会崩溃。

想象一下:1。)输入为空。 2.)我快速输入“测试”。 3.)doSearch函数甚至没有被触发,我点击cmd -a选择all并删除输入中的文本。

我的网站完全崩溃了!

为什么会这样? 当我只是在输入doSearch()时输入“test”或删除输入时,它确实工作得非常顺畅和精确。 它实际上总是有效。 正是在极少数情况下快速输入并在doSeach()事件中删除键入的文本时,它崩溃了。

知道是什么原因引起的吗?

编辑/更新:当我将sitemap.html复制到我当前的procets根目录并加载它时,它不会崩溃并且在您的示例中正常工作。 一旦我将其更改为url: "sitemap", dataType: "html",它就会崩溃。 我使用mydomain.com/sitemap调用我的站点地图…

站点地图的代码如下所示:

    

Pages

Posts

  • <a href="https://stackoverflow.com/questions/5370032/jquery-ajax-based-search-browser-crash/#b">

Categories

Tags

抱歉这最后一个问题,但任何想法为什么会有所作为。 当我使用此动态/站点地图作为我的搜索的基础时,浏览器崩溃。 使用静态html页面,它工作正常。

我想您的代码的主要问题是您不会中止先前挂起的ajax调用。 如果同时尝试在两个服务器响应上修改$sr元素,浏览器会发生什么?

旧的XMLHttpRequest和新的jqXHR都有可以使用的中止方法。

更新 :正如我在评论中所描述的那样, jQuery.load不再像jQuery.ajax调用和jQuery.html那样将服务器响应放在页面上。 您可以在此处查看jQuery.load的源代码(对于jQuery 1.4.4)或此处 (对于jQuery 1.5.1)。

我为你准备了一个小的演示示例,它展示了如何直接使用jQuery.ajax和jQuery.html而不是jQuery.load 。 您可以在此处下载完整项目。

如果慢慢地在演示的输入框中键入一个,则会收到以下结果 在此处输入图像描述

如果一个类型更快(我打字很慢,所以在服务器上使用1秒超时): 在此处输入图像描述

可以看到,如果存在任何挂起的ajax请求,我会将之前的ajax请求中止到服务器。 在中止相应(先前)的error处理程序的情况下,调用ajax请求然后返回abort()函数。

我希望如果你遵循这样的方式,你将永远不会遇到你在问题中描述的问题。

为了确保您收到示例,我在下面提供了我在测试演示中使用的完整代码。 JavaScript代码如下

 var jqXHR_Old, $myinput = $('#myinput'), $result = $('#result'), $protocol = $('#protocol'), logText = function(txt) { $protocol.append(txt+"
"); // append or prepend }, doSearch = function(code) { var txt = $myinput.val(); if (txt != '') { // send request to the server if (jqXHR_Old) { // abort the previous request logText("aborting..."); jqXHR_Old.abort(); jqXHR_Old = null; } $result.empty(); logText('sending request to the server with '+ ''+txt+'...'); jqXHR_Old = $.ajax({ url: "MySimpleService.svc/GetTestHtmlFragment", data: {str:txt}, dataType: "html", success: function (data) { $result.html(data); logText("received from the server: "+data); jqXHR_Old = null; }, error: function (XMLHttpRequest, textStatus, errorThrown) { if (textStatus !== "abort" || errorThrown !== "abort") { $result.html("Error Occured!" + " | " + " | " + textStatus + " | " + errorThrown + "responseText:
" + XMLHttpRequest.responseText); } else { logText("request aborted."); } jqXHR_Old = null; } }); } }; $myinput.keyup(function(e) { switch (e.keyCode) { //case 8: // Backspace case 9: // Tab case 13: // Enter doSearch(e.keyCode); break; case 37: // Left break; case 38: // Up doSearch(e.keyCode); break; case 39: // Right break; case 40: // Down doSearch(e.keyCode); break; default: doSearch(e.keyCode); } });

HTML就在这里

 
Results from the server:
Ajax protocol:

作为服务器,我使用非常简单的WCF服务与接口

使用System.ServiceModel; 使用System.ServiceModel.Web; 使用System.ServiceModel.Channels;

 namespace AjaxLoad { [ServiceContract] public interface ISimpleService { [OperationContract] [WebGet] Message GetTestHtmlFragment (string str); } } 

和实施

 using System.ServiceModel.Activation; using System.ServiceModel.Web; using System.ServiceModel.Channels; using System.Text; using System.Threading; namespace AjaxLoad { [AspNetCompatibilityRequirements (RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class SimpleService : ISimpleService { public Message GetTestHtmlFragment (string str) { Thread.Sleep (1000); return WebOperationContext.Current.CreateTextResponse ("" + str + "", "text/html; charset=utf-8", Encoding.UTF8); } } } 

我使用Thread.Sleep模拟慢速请求处理,等待1秒。 我使用SVC文件免费实现,因此用作web.config

                            

作为项目的“引用”,需要三个依赖程序集:System,System.ServiceModel,System.ServiceModel.Web。

试试这个:

 var searchTimer; //define the scope of searchTimer and set it to null /* ...code...*/ if (searchTimer != null) { clearTimeout(searchTimer); } 

超时的ID始终从0开始,随着更多定时器的创建而上升。