2013-09-30 10 views
6

Ich schreibe einen JavaScript-API-Client mit jQuery. Meine Top-Level-Request-Methode sieht wie folgt aus:Geben Sie eine Standardmethode für ein fehlgeschlagenes jQuery-Objekt an

function request(method, uri, params, proxies) { 
    var deferred = $.Deferred(); 
    $.ajax({ 
    data: method == 'GET' ? params : JSON.stringify(params), 
    contentType: 'application/json', 
    dataType: 'json', 
    url: api.root + uri, 
    type: method, 
    xhrFields: { 
     withCredentials: true 
    } 
    }).done(function(body) { 
    deferred.resolveWith(this, [body.data]); 
    }).fail(function(xhr) { 
    deferred.rejectWith(this, [xhr]); 
    }); 

    return deferred.promise(); 
}, 

Wie kann ich einen Standard fail Handler für meine latente zurückgegeben? Das heißt, wenn der Deferred keine anderen Handler an seine fail Bedingung angehängt hat, rufen Sie einen Standard-Handler auf.

Ich möchte dies globale Ausnahmebehandlung in meiner Anwendung haben, mit Ausnahme der Teile, die eine spezifische Behandlung haben (und ihre eigenen fail Handler auf die zurückgestellte definieren).

+5

latente Objekte funktionieren nicht dieser Weg. Verwenden Sie stattdessen einen globalen Fehlerhandler und deaktivieren Sie dann globale Ereignisse für diese AJAX-Anforderung. –

+0

Verwenden Sie nicht die "$ .Deferred" -Schnittstelle hier. Rufen Sie einfach die 'then'-Methode (oder' pipe' in alten jQuery-Versionen) auf, die von '$ .ajax()' zurückgegeben wird! – Bergi

+0

Es gibt ein globales ['ajaxError'-Ereignis] (http://api.jquery.com/ajaxError/), und Sie können [' $ .ajaxSetup'] (http://api.jquery.com/jQuery.ajaxSetup verwenden /) für Standardoptionen. – Bergi

Antwort

3

Also, der sauberste Weg, um jQuery AJAX in einer API ab 2016 zu verwenden, ist eine Versprechen zurückzugeben. Sie können jedoch nicht feststellen, ob ein Aufrufer einen Fehlerhandler an das Versprechen angehängt hat oder nicht.

Also, was ich vorschlagen würde, ist, dass Sie einfach ein neues Argument zu Ihrer Funktion hinzufügen, die der Funktion sagt, die Standardfehlerbehandlung NICHT anzuwenden, weil der Anrufer sich um die Fehlerbehandlung kümmern wird. Und ich würde vorschlagen, dass Sie das Versprechen anti-Muster vermeiden, indem nur die bestehende Versprechen mit $.ajax() bereits zurückgibt, anstatt die Erstellung Ihrer eigenen latenten:

function request(method, uri, params, proxies, skipDefaultErrorHandling){ 
    // default error handling will be used if nothing is passed 
    // for skipDefaultErrorHandling 
    var p = $.ajax({ 
     data: method=='GET'?params:JSON.stringify(params), 
     contentType: 'application/json', 
     dataType: 'json', 
     url: api.root + uri, 
     type: method, 
     xhrFields: { 
      withCredentials: true 
     } 
    }); 
    if (!skipDefaultErrorHandling) { 
     // apply default error handling 
     p = p.then(null, function(jqXHR, textStatus, errorThrown) { 
      // put here whatever you want the default error handling to be 
      // then return the rejection with the various error parameters available 
      return $.Deferred().reject([jqXHR, textStatus, errorThrown]); 
     }); 
    } 

    return p; 
}; 

Dann entscheidet der Anrufer nur, ob ihre eigene Fehlerbehandlung anwenden oder nicht:

request(...).then(function(data) { 
    // success code here 
}); 

oder können Sie mit einem nicht-Versprechen failHandler Rückruf gehen, die Sie und Ihre Standard-Fehlerbehandlung sehen passieren zu sehen, ob die failHandler in oder nicht bestanden wurde. Dies ist Hybrid-Versprechungen und Rückrufe und ist nicht etwas, was ich normalerweise Architekten wählen würde, aber da Ihre Frage nach etwas fragt, die nicht unterstützen, verspricht, ist dies ein zu erreichen, dass:

function request(method, uri, params, proxies, failHandler){ 
    // default error handling will be used if nothing is passed 
    // for skipDefaultErrorHandling 
    var p = $.ajax({ 
     data: method=='GET'?params:JSON.stringify(params), 
     contentType: 'application/json', 
     dataType: 'json', 
     url: api.root + uri, 
     type: method, 
     xhrFields: { 
      withCredentials: true 
     } 
    }); 
    // apply default error handling 
    p = p.then(null, function(jqXHR, textStatus, errorThrown) { 
     if (failHandler) { 
      // call passed in error handling 
      failHandler.apply(this, arguments); 
     } else { 
      // do your default error handling here 
     } 
     // then keep the promise rejected so the caller doesn't think it 
     // succeeded when it actually failed 
     return $.Deferred().reject([jqXHR, textStatus, errorThrown]); 
    }); 

    return p; 
};