2012-03-29 13 views
11

Ho il seguente codice, che mi sta dando un messaggio Method POST, Status (canceled) di errore:metodo POST, messaggio Stato (annullato) errore

$(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."); 
    } 

}); 

Il codice effettivamente funziona a patto che ogni richiesta AJAX completa, ma se devo scrivere velocemente in txt1, ovvero digita il carattere successivo prima che la richiesta precedente termini, ricevo il messaggio di errore Method POST, Status (canceled).

Qualcuno sa perché questo sta accadendo e come correggere l'errore?

+0

Questo può essere utile, dare un'occhiata [stackoverflow.com/questions/6678467](http://stackoverflow.com/questions/6678467/ajax-sent-on-keyup-duplicates-results-when-fast-typing) – safarov

+0

Oleg ha probabilmente la migliore risposta qui. La sua correzione dovrebbe aiutarti ad andare oltre con la sceneggiatura. TUTTAVIA: leggendo il tuo codice vedo che non stai creando il codice ideale per questo problema. Creerò una risposta per te. –

risposta

11

Suppongo che il problema sia molto semplice. Se si chiama xhr.abort();, la richiamata error di $.ajax si chiamerà per la richiesta in sospeso. Quindi dovresti semplicemente ignorare questo caso all'interno del callback error. Così il gestore error può essere modificato per

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. Probabilmente un altro mio old answer sul problema di chiusura potrebbe anche essere interessante per te.

0

Questo perché si chiama il metodo abort che probabilmente attiva il gestore degli errori con il messaggio di errore appropriato.

È possibile attendere la richiesta di ajax precedente prima di effettuare la chiamata successiva.

+0

Come dovrei interrompere un processo che non è terminato se è necessario avviare un altro al suo posto? – oshirowanen

-1

Ajax è un tipo asincrono, la sua non recommonded che u per inviare richiesta su ogni evento keyup, provate il ...

async: false 

nel metodo post ... che sarà mettere in pausa i messaggi successivi fino a quando il la richiesta corrente ha effettuato la richiamata

+3

L'uso di 'async: false' non è auspicabile in quanto interromperà il browser fino al completamento e alla risposta della richiesta. – ShankarSangoli

+0

Sono d'accordo. Con questa soluzione distruggi l'intera possibilità di aggiungere contenuti dinamicamente mentre stai scrivendo. –

0

Si sta utilizzando l'evento keyup, che sembra essere il problema.

In caso di necessità, è necessario attendere dopo aver digitato un carattere prima di agire.

Una soluzione migliore potrebbe essere quella di seguire la stessa strategia del JQuery AutoComplete COmponent.

-1

Realisticamente è necessario un metodo setTimeout per evitare l'attivazione di chiamate ajax ridondanti.

clearTimeout(timer); 

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

Questo dovrebbe eliminare il problema.

+0

In che modo questa risposta non è utile? – trickyzter

0

Per risolvere entrambi i problemi e risparmiare sulla quantità di chiamate Ajax ho scritto il seguente esempio. Questo esempio consente di gestire due situazioni seguenti:

Situazione 1:

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

Situazione 2:

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

Nel seguente esempio non v'è alcuna necessità di interrompere o ignorare le chiamate Ajax, non si sta inviando spam alle chiamate Ajax e si sta utilizzando un oggetto per gestire il proprio lavoro.(Ho anche jsFiddled per voi)

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

}); 

Spero che questo aiuti.

Problemi correlati