11

我有以下代码,它给了我一条Method POST, Status (canceled)错误消息:

$(document).ready(function() {
    var xhr = false;

    get_default();

    $('#txt1').keyup( function() {
        if(xhr && xhr.readyState != 4){
            alert("abort");
            xhr.abort();
        }

        if ($("#txt1").val().length >= 2) {
            get_data( $("#txt1").val() );
        } else {
            get_default();
        }
    });

    function get_data( phrase ) {
        xhr = $.ajax({
            type: 'POST',
            url: 'http://intranet/webservices.asmx/GetData',
            data: '{phrase: "' + phrase + '"}',
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            success: function( results ) {
                $("#div1").empty();

                if( results.d[0] ) {
                    $.each( results.d, function( index, result ) {
                        $("#div1").append( result.Col1 + ' ' + result.Col2 + '<br />' );
                    });
                } else {
                    alert( "no data available message goes here" );
                }
            },
            error: function(xhr, status, error) {
                 var err = eval("(" + xhr.responseText + ")");
                 alert(err.Message) ;
            }
        });
    }

    function get_default() {
        $('#div1').empty().append("default content goes here.");
    }

});

只要每个 ajax 请求完成,代码实际上就可以工作,但是如果我快速输入txt1,即在前一个请求完成之前输入下一个字符,我会收到错误消息Method POST, Status (canceled)

任何人都知道为什么会发生这种情况以及如何纠正错误?

4

6 回答 6

11

我想这个问题很简单。如果您调用,xhr.abort();则将为挂起的请求调用error回调。所以你应该在回调中忽略这种情况。所以处理程序可以修改为$.ajaxerrorerror

error: function(jqXHR, textStatus, errorThrown) {
    var err;
    if (textStatus !== "abort" && errorThrown !== "abort") {
        try {
            err = $.parseJSON(jqXHR.responseText);
            alert(err.Message);
        } catch(e) {
            alert("ERROR:\n" + jqXHR.responseText);
        }
    }
    // aborted requests should be just ignored and no error message be displayed
}

PS 可能我对关闭问题的另一个旧答案对您来说也很有趣。

于 2012-04-01T14:05:12.227 回答
0

In order to both fix your problem and save on the amount of Ajax calls I have written the following example. This example allows you to handle the following two situations:

Situation 1:

The user types slow enough (lets say about one key every 200+ miliseconds

Situation 2:

The user types fast (my average is about 20 to 50 miliseconds per key)

In the following example there is no need to abort or ignore Ajax calls, you are not spamming Ajax calls and you are using an Object to handle your job. (I even jsFiddled it for you)

var Handler = {

    /**
     * Time in ms from the last event
     */
    lastEvent: 0,

    /**
     * The last keystroke must be at least this amount of ms ago
     * to allow our ajax call to run
     */
    cooldownPeriod: 200,

    /**
     * This is our timer
     */
    timer: null,

    /**
     * This should run when the keyup event is triggered
     */
    up: function( event )
    {
        var d = new Date(),
            now = d.getTime();

        if( ( now - Handler.lastEvent ) < Handler.cooldownPeriod ) {
           // We do not want to run the Ajax call
            // We (re)set our timer
            Handler.setTimer();
        } else {
            // We do not care about our timer and just do the Ajax call
            Handler.resetTimer();
            Handler.ajaxCall();
        }

        Handler.lastEvent = now;
    },

    /**
     * Function for setting our timer
     */
    setTimer: function()
    {
        this.resetTimer();
        this.timer = setTimeout( function(){ Handler.ajaxCall() }, this.cooldownPeriod );
    },

    /**
     * Function for resetting our timer
     */
    resetTimer: function()
    {
        clearTimeout( this.timer );
    },

    /**
     * The ajax call
     */
    ajaxCall: function()
    {
        // do ajax call
    }

};

jQuery( function(){

    var field = jQuery( '#field' );

    field.on( 'keyup', Handler.up );

});

Hope this helps.

于 2012-04-05T12:58:23.840 回答
0

您正在使用该keyup事件,这似乎是问题所在。

如果有的话,您需要在输入一个字符后等待,然后再采取行动。

更好的解决方案可能是遵循与JQuery AutoComplete COmponent.

于 2012-04-01T12:37:51.090 回答
0

那是因为您正在调用abort可能会触发带有适当错误消息的错误处理程序的方法。

您可以等待上一个 ajax 请求完成,然后再进行下一次调用。

于 2012-03-29T15:37:08.923 回答
-1

实际上,您需要一个 setTimeout 方法来防止触发多余的 ajax 调用。

clearTimeout(timer);

if($("#txt1").val().length >= 2){
    timer = setTimeout(function(){
        get_data($("#txt1").val());
    }, 400);
}else{
    get_default();
}

这应该可以消除您的问题。

于 2012-04-04T22:02:19.457 回答
-1

Ajax 是一种异步类型,不建议您在每个 keyup 事件上发送请求,尝试...

async: false

在 post 方法中...它将暂停后续的帖子,直到当前请求完成其回调

于 2012-03-29T15:38:45.660 回答