这实际上非常好,但是有一个小错误可能导致我的浏览器崩溃。
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 ...
站点地图的代码如下所示:
<?php
/**
* Template Name: Sitemap
*/
?>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<div id="ajax-base">
<h3>Pages</h3>
<ul>
<?php wp_list_pages('title_li=&depth=0&exclude='); ?>
</ul>
<h3>Posts</h3>
<?php $first = 0;?>
<ul>
<?php
$myposts = get_posts('numberposts=-1&offset=$first');
foreach($myposts as $post) :
?>
<li><a href="<?php the_permalink(); ?>#b"><?php the_title(); ?></a></li>
<?php endforeach; ?>
</ul>
<h3>Categories</h3>
<ul>
<?php wp_list_categories('title_li=&orderby=name'); ?>
</ul>
<h3>Tags</h3>
<ul>
<?php
$tags = get_tags();
foreach ($tags as $tag){
$tag_link = get_tag_link($tag->term_id);
$html .= "<li><a href='{$tag_link}#b' title='{$tag->name} Tag' class='{$tag->slug}'>";
$html .= "{$tag->name}</a></li>";
}
echo $html;
?>
</ul>
</div> <!-- ajax-base -->
<?php endwhile; endif; ?>
抱歉这最后一个问题,但任何想法为什么会有所作为。当我使用此动态/站点地图作为我的搜索基础时,浏览器崩溃。使用静态html页面可以正常工作。
答案 0 :(得分:4)
我认为您的代码的主要问题是您不会中止之前的待处理ajax调用。如果同时尝试修改两个服务器响应上的$sr
元素,浏览器会发生什么?
旧XMLHttpRequest
和新jqXHR
都有abort方法,您可以使用。
更新:正如我在评论中所述,jQuery.load与jQuery.ajax调用相比更多,jQuery.html将服务器响应放在页面上。您可以在jQuery.load
here(对于jQuery 1.4.4)或here(对于jQuery 1.5.1)的源代码中进行验证。
我为您准备了一个小型演示示例,其中展示了如何直接使用jQuery.ajax和jQuery.html代替jQuery.load。您可以下载完整的项目here。
如果演示文稿缓慢的输入框中有一个类型,则会收到以下结果
如果一个类型更快(我打字很慢,所以在服务器上使用1秒超时):
如果存在任何待处理的ajax请求,我可以看到我将之前的ajax请求中止到服务器。如果中止,则调用相应(先前)ajax请求的error
处理程序,然后abort()
函数返回。
我希望如果你遵循这样的方式,你将永远不会遇到你在问题中描述的问题。
为了确保您收到示例,我在下面提供了我在测试演示中使用的完整代码。 JavaScript代码如下:
var jqXHR_Old, $myinput = $('#myinput'),
$result = $('#result'), $protocol = $('#protocol'),
logText = function(txt) {
$protocol.append(txt+"<br/>"); // 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 '+
'<span style="color:blue;">'+txt+'</span>...');
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:<br/>" + 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就在这里
<fieldset style="float:left">
<input type="text" id="myinput"/>
</fieldset>
<div style="clear:left">
<fieldset style="float:left">
<legend>Results from the server:</legend>
<div id="result"></div>
</fieldset>
<div style="clear:left"/>
<fieldset style="float:left">
<legend>Ajax protocol:</legend>
<div id="protocol"></div>
</fieldset>
</div>
作为服务器,我使用非常简单的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 ("<span style='color:red'>" + str + "</span>",
"text/html; charset=utf-8",
Encoding.UTF8);
}
}
}
我只用Thread.Sleep
模拟慢速请求处理,等待1秒钟。我使用SVC文件免费实现,因此用作web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<standardEndpoints>
<webHttpEndpoint>
<!-- the "" standard endpoint is used by WebServiceHost for auto creating a web endpoint. -->
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" />
</webHttpEndpoint>
</standardEndpoints>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true">
<serviceActivations>
<add relativeAddress="MySimpleService.svc" service="AjaxLoad.SimpleService"
factory="System.ServiceModel.Activation.WebServiceHostFactory" />
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
</configuration>
作为项目的“引用”需要三个依赖程序集:System,System.ServiceModel,System.ServiceModel.Web。
答案 1 :(得分:0)
试试这个:
var searchTimer; //define the scope of searchTimer and set it to null
/* ...code...*/
if (searchTimer != null) {
clearTimeout(searchTimer);
}
超时的ID始终从0开始,随着更多定时器的创建而上升。