jQuery:基于Ajax的搜索-浏览器崩溃? [英] jquery: ajax based search - browser crash?

查看:63
本文介绍了jQuery:基于Ajax的搜索-浏览器崩溃?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

hey guys, i'm working on a rather weird ajax based search model. The search is not actually retrieving real searchresults from the server but rather loads the website's sitemap (with the jquery load() method) and extracts its links.

实际上效果很好,但是有一个小错误可能会导致我的浏览器崩溃.

That works actually really good, but there is one little bug that might cause my browser to crash.

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内将其删除,该网站就会崩溃.

The only problem I have with this is that the site crashes once I type a word in my .s input field and immediately delete it within the 250ms.

想象一下: 1.)输入为空. 2.)我快速输入测试". 3.)doSearch函数甚至还没有被触发,我按cmd-a选中所有内容并删除输入中的文本.

Imagine this: 1.) the input is empty. 2.) i quickly type "test". 3.) the doSearch function hasn't even been fired and I hit cmd-a to select all and remove the text in the input.

我的网站完全崩溃!

为什么会发生这种情况?当我刚刚输入"test"或在doSearch()被触发后删除输入时,它的工作确实非常流畅和良好.实际上,它始终有效.只是在这种罕见的情况下,如果快速键入并在doSeach()事件中删除键入的文本,它就会崩溃.

Why could that happen? It does work really smooth and fine when I just type "test" or delete the input once the doSearch() has been fired. It actually works always. Just in this rare case of typing quickly and removing the typed text within the event of doSeach() it crashes.

有什么想法会导致这种情况吗?

Any idea what could cause that?

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

edit/update: When I copy sitemap.html into my current procets root directory and load it doesn't crash and works fine as in your example. As soon as i change it to url: "sitemap", dataType: "html", it crashes. I call my sitemap with 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; ?>

很抱歉这是最后一个问题,但是不知道为什么会有所作为.当我使用此动态/sitemap作为搜索基础时,浏览器崩溃.使用静态html页面,效果很好.

sorry for this last question, but any idea why that makes a difference. When I use this dynamic /sitemap as basis for my search the browser crashes. With a static html page it works fine.

推荐答案

我认为您代码的主要问题是您不会放弃前一个待处理的

I suppose the main problem of your code is that you don't abort the previous pending ajax call. What happens in the browser if it simultaneously will try to modify $sr element on two server response?

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

Both old XMLHttpRequest and new jqXHR has abort method which you can use.

更新:如我在评论中所述, jQuery.load 仅作为 jQuery.ajax 调用和此处(对于jQuery 1.4.4)或

UPDATED: As I described in the comment the jQuery.load do not much more as the jQuery.ajax call and jQuery.html to place the server response on the page. You can verify this looking in the source code of jQuery.load here (for jQuery 1.4.4) or here (for jQuery 1.5.1).

我为您准备了一个小型演示示例,展示了如何使用 jQuery.ajax jQuery.html 而不是此处下载完整的项目.

I prepared one small demo example for you which shows how you can use jQuery.ajax and jQuery.html directly instead of jQuery.load. You can download the full project here.

如果一种在演示的输入框中键入缓慢,则一种会收到以下结果

If one types in the input box of the demo slowly one receive the following results

如果输入速度更快(我输入的速度很慢,因此在服务器上使用1秒超时):

If one types more quickly (I type very slow and so use 1 sec timeout on the server):

可以看到,如果存在任何待处理的ajax请求,那么我将中止对服务器的上一个ajax请求.如果中止相应(先前)ajax请求的error处理程序,然后调用abort()函数.

One can see that I abort the previous ajax request to the server if any pending ajax request exist. In case of aborting the error handler of the corresponding (previous) ajax request are called and then the abort() function return.

我希望如果您按照这种方式做,就永远不会遇到问题中所描述的问题.

I hope if you follow the way you will never have the problems which you describes in your question.

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

To be sure that you receive the example I include the full code, which I used in my test demo, below. The JavaScript code is following

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服务

As the server I use very simple WCF service with the interface

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

using System.ServiceModel; using System.ServiceModel.Web; using 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

I simulate slow request processing just with Thread.Sleep with 1 sec waiting. I used SVC file free implementation and so used as 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.

As "References" of the project three dependent assemblies needed: System, System.ServiceModel, System.ServiceModel.Web.

这篇关于jQuery:基于Ajax的搜索-浏览器崩溃?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆