35

Ho un modello Backbone.js che sto cercando di distruggere quando l'utente fa clic su un collegamento nella vista del modello. La vista è simile a questa (pseudocodice perché è implementata in CoffeeScript che può essere trovata in fondo alla domanda).Backbone model.destroy() che richiama la funzione di callback degli errori anche quando funziona correttamente?

var window.ListingSaveView = Backbone.View.extend({ 
    events: { 
    'click a.delete': 'onDestroy' 
    }, 

    onDestroy: function(event){ 
    event.preventDefault(); 
    this.model.destroy({ 
     success: function(model, response){ 
     console.log "Success"; 
     }, 
     error: function(model, response){ 
     console.log "Error"; 
     } 
    }); 
    } 
}); 

quando clicco il link delete nel browser, ho sempre arrivare Error registrato alla console anche se i miei record dei server di distruzione di successo del record del database associato e restituisce una risposta 200. Quando aggiorno la pagina (causando il re-rendering della raccolta dal DB) il modello che ho eliminato sarà scomparso.

Un interessante questo è che quando accedo il response nella richiamata errore, ha StatusCode 200 che indica il successo, ma anche i rapporti statusText: "parseerror" qualunque cosa ciò significhi. Non c'è nessun errore nei miei log del server.

Cosa sto sbagliando?

Questa è la risposta dal server:

Object 
    abort: function (statusText) { 
    always: function() { 
    complete: function() { 
    done: function() { 
    error: function() { 
    fail: function() { 
    getAllResponseHeaders: function() { 
    getResponseHeader: function (key) { 
    isRejected: function() { 
    isResolved: function() { 
    overrideMimeType: function (type) { 
    pipe: function (fnDone, fnFail) { 
    promise: function (obj) { 
    readyState: 4 
    responseText: " " 
    setRequestHeader: function (name, value) { 
    status: 200 
    statusCode: function (map) { 
    statusText: "parsererror" 
    success: function() { 
    then: function (doneCallbacks, failCallbacks) { 
    __proto__: Object 

Ecco l'azione del server che distruggono interagisce con (Ruby on Rails)

# DELETE /team/listing_saves/1.json 
    def destroy 
    @save = current_user.team.listing_saves.find(params[:id]) 
    @save.destroy 
    respond_to do |format| 
     format.json { head :ok } 
    end 
    end 

E qui è l'implementazione effettiva CoffeeScript della spina dorsale Visualizza per le persone che lo preferiscono:

class MoveOutOrg.Views.ListingSaveView extends Backbone.View 
    tagName: 'li' 
    className: 'listing_save' 
    template: JST['backbone/templates/listing_save'] 
    events: 
    'click a.delete_saved': 'onDestroy' 

    initialize: -> 
    @model.bind 'change', this.render 
    render: => 
    renderedContent = @template(@model.toJSON()) 
    $(@el).html(renderedContent) 
    this 
    onDestroy: (event) -> 
    event.preventDefault() # stop the hash being added to the URL 
    console.log "Listing Destroyed" 
    @model.destroy 
     success: (model, response)-> 
     console.log "Success" 
     console.log model 
     console.log response 

     error: (model, response) -> 
     console.log "Error" 
     console.log model # this is the ListingSave model 
     console.log response 
+0

Puoi incollare tutto ciò che il server invia indietro (usa firebug o qualcosa per aprire la risposta), se non altro? – Stephen

+0

Modificato la mia domanda per includere la risposta –

+1

Oh. Bene, per essere sinceri .. questa non è una risposta valida. È molto probabile che ascolti una risposta JSON ... e in un modo o nell'altro non la stai dando. Non riesco a ricordare quello che usiamo al lavoro per i binari, ma è qualcosa come to_json, non solo 'json' (non sono un esperto di rubini .. o anche un novizio .. quindi non posso fare a meno di farlo) – Stephen

risposta

51

@David Tuite comm ent:

"Ok, l'ho capito. Sembra che Backbone si aspetti che la risposta JSON sia una serializzazione JSON del record che è stata distrutta. Tuttavia, i generatori di controller Rails restituiscono solo head: ok di default. Ho cambiato la mia risposta JSON di essere rendere JSON: @listing_save dove @listing_save è il disco che ho appena distrutto e registra un successo "

CRONACA - quando si sta facendo un distruggere, non è necessario. restituire l'intero json per il modello distrutto, è possibile restituire un hash JSON vuoto e funzionerà correttamente, l'unica volta che è necessario restituire il JSON per il modello è in un salvataggio/aggiornamento

+3

ok ok puoi avere i punti. Anche se ho fatto metà del lavoro;) –

+0

backbone è così sensibile alle rotaie json result –

+2

Mentre non è necessario restituire il modello, è abbastanza bello farlo a volte. Un caso in cui questo è davvero un buon approccio è quando non si utilizza il parametro {wait: true} del destroy - in questo modo, se l'azione fallisce, è possibile aggiungere facilmente il modello alla raccolta, per mantenere la collezione aggiornato. –

0

Sei sicuro di il tuo URL? aggiungi un .json alla fine dell'URL Backbone.Model? Dal momento che controlli questo sul lato server (rispondi a do | format | ... end), potresti non inviare la risposta head :ok corretta

Prova con questo metodo destroy rotaie per verificare se questo è il problema:

def destroy 
    @save = current_user.team.listing_saves.find(params[:id]) 
    @save.destroy 
    head :ok 
end 
7

La vostra risposta deve avere il codice di stato 204 in quanto non sarà tornare alcun contenuto. Poiché il backbone utilizza un'interfaccia REST, è necessario restituire diversi codici di stato http in base all'attività.

16

Ho avuto lo stesso problema. Nel mio metodo di eliminazione sul server (java), non ho restituito nulla. Solo stato 200/OK (o 204/Nessun contenuto). E così il problema "parsererror" è stato causato da jquery che prova a convertire la risposta vuota in JSON, che non ha funzionato (poiché "json" è il tipo di dati predefinito).

La mia soluzione era quella di utilizzare il tipo di dati "testo", invece, che può essere impostato nelle opzioni:

model.destroy({ dataType: "text", success: function(model, response) { 
    console.log("success"); 
}}); 
+0

Bella cattura. Grazie. – chikamichi

+2

Ho anche usato 'model.destroy ({contentType: false, processData: false})'. – carpeliam

0

Utilizzando il quadro Slim su un server LAMP è possibile aggiungere un Response Status a DELETE percorsi (o personalizzato percorsi che non restituiscono nulla)

$app->response()->status(204);//204 No Content

questa imposta anche il Content-Type torna al testo/html per consentire il corpo vuoto

Problemi correlati