Сообщение об ошибке метод POST, Status (cancelled)

у меня есть следующий код, который дает мне 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).

кто-нибудь знает, почему это происходит и как исправить ошибку?

6 ответов


Я полагаю, что проблема очень проста. Если вы позвоните xhr.abort(); тут error вызов $.ajax будет называться на запрос. Поэтому вы должны просто игнорировать такой случай внутри error обратный. Так что error обработчик можно изменить на

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
}

P. S. наверное еще один мой ответ на близкой проблеме также может быть интересно для вас.


это потому, что ты называешь abort метод, который может инициировать обработчик ошибок с соответствующим сообщением об ошибке.

вы можете дождаться завершения предыдущего запроса ajax перед выполнением следующего вызова.


чтобы исправить вашу проблему и сэкономить на количестве вызовов Ajax, я написал следующий пример. Этот пример позволяет обрабатывать следующие две ситуации:

Ситуация 1:

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

Ситуация 2:

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

в следующем примере нет необходимости прерывать или игнорировать вызовы Ajax, вы не спам-вызовы Ajax, и вы используете объект для обработки вашей работы. (Я даже jsFiddled это для тебя)

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 );

});

надеюсь, что это помогает.


вы используете keyup событие, которое, похоже, является проблемой.

Если что-нибудь вообще, нужно подождать после ввода одного символа, прежде чем принимать решение.

лучшим решением может быть следовать той же стратегии, что и JQuery AutoComplete COmponent.


Ajax является асинхронным типом, его не рекомендуется отправлять запрос на каждое событие keyup, попробуйте...

async: false

в методе post... он приостановит последующие сообщения, пока текущий запрос не выполнит обратный вызов


реалистично Вам нужен метод setTimeout, чтобы предотвратить запуск избыточных вызовов ajax.

clearTimeout(timer);

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

Это должно устранить вашу проблему.