2013-06-25 4 views
5

In jQuery, wenn Sie einen Fehler in Ihrer Ajax Callback-Methode machen, erhalten Sie eine ordnungsgemäße Konsole Fehlermeldung und Stacktrace.Dojo - ReferenceError Ausnahme im Versprechen wird geschluckt

$.get("https://api.github.com/users/octocat/orgs", function() { 
    var a = FAIL; 
}); 

In Dojo mit dojo/request/xhr scheint es jedoch, dass diese dummen Fehler vollständig verschluckt werden. Die einzige Sache in meiner Konsole, wenn ich das führe, ist "dann" und "immer".

require(["dojo/request/xhr" ], function(xhr) { 
    var promise = xhr.get("https://api.github.com/users/octocat/orgs"); 
    promise.then(function(data) { 
     console.log('then'); 
     var a = FAIL; 
     console.log('goodbye'); 
    }, function() { 
     console.log('error'); 
    }); 
    promise.otherwise(function() { 
     console.log('otherwise'); 
    }); 
    promise.always(function() { 
     console.log('always'); 
    }); 
}); 

Mit der veralteten Dojo.xhrGet wird das Problem sehr leicht verbessert. Ich erhalte eine Konsole Fehlermeldung und meine Fehler-Handler aufgerufen wird, aber es sagt nur „Reference {}“ und bietet mir einen Stack-Trace, die nie auf eine Funktion verweist ich besitze:

dojo.xhrGet({ 
    url: "https://api.github.com/users/octocat/orgs", 
    load: function() { 
     console.log('dojo.xhrGet.load'); 
     var a = FAIL; 

     console.log('goodbye dojo.xhrGet.load'); 
    }, 
    error: function() { 
     console.log('dojo.xhrGet.error'); 
    }, 
    handle: function() { 
     console.log('dojo.xhrGet.handle'); 
    } 
}); 

Wenn ein Programm schreiben, wir machen Fehler, es ist schön, dass wir Tools wie Chrome-Entwicklerwerkzeuge haben, um uns auf diese Fehler hinzuweisen. Die Zeit, die benötigt wird, um einen Fehler zu finden, wenn Sie einen Stacktrace und eine Fehlermeldung sehen, ist offensichtlich viel schneller als wenn Sie keine Rückmeldung erhalten. Ich bekomme im Dojo kein Feedback, ich kann nicht glauben, dass eine so populäre Bibliothek so funktionieren könnte. Was mache ich falsch?

Antwort

4

Das Verständnis von Versprechungen, die Sie von jQuery geerbt zu dem einen alle anderen grundlegend anders ist (überprüfen Promises/a + Implementierungen) hat. Für den Rest dieser Antwort werde ich über Versprechen/a + konforme Versprechen sprechen. Dojo's Deferred ist eigentlich nicht + konform, aber es ist nah genug, dass alles, was ich hier diskutiere, genauso gut zutrifft.

Versprechungen sind unveränderlich, Sie können einen Versprechungsstatus nicht ändern, indem Sie then aufrufen. Ein Versprechen stellt einen eventuellen Wert dar, es wäre unsinnig, die Verheißung ändern zu können, indem man sagt "sobald der Wert bereit ist, tue dies".

Also, hoffentlich erklärt das, warum Ihr Fehlerhandler nicht aufgerufen wird, aber die Grundidee, Fehler zu fangen, ist immer noch völlig möglich. Sie müssen nur Rückgabewerte verwenden. Wenn Sie auf ein Versprechen then aufrufen, gibt es ein neues und (fast immer) anderes Versprechen zurück. Dieses neue Versprechen ist sehr speziell, wenn das Original aufgelöst wird und der von Ihnen übergebene Erfolgshandler aufgerufen wird und etwas zurückgibt, dass etwas der Auflösungswert des zweiten Versprechens ist.

Wenn der Fehlerhandler (beim ersten Versprechen) ebenfalls ausgelöst wird und diese Funktion etwas zurückgibt, entspricht dieser Wert dem Auflösungswert des zweiten Versprechens. Dasselbe gilt für geworfene Fehler, sie werden an den Error-Handler übergeben (des zweiten Versprechens!).

Also hier ist Ihr erstes Codebeispiel in einem Versprechen/a + Art und Weise mehr geschrieben:

require(["dojo/request/xhr" ], function(xhr) { 
    var promise = xhr.get("https://api.github.com/users/octocat/orgs"); 
    promise.then(function(data) { 
     console.log('then'); 
     var a = FAIL; 
     console.log('goodbye'); 
    }, function() { 
     console.log('error'); 
    }).then(null, function() { 
     console.log('otherwise'); 
    }); 

    promise.always(function() { 
     console.log('always'); 
    }); 
}); 

Ich verstehe wirklich nicht, was Sie mit der immer Funktion tun wollen, so war ich nicht sicher, wo Setze das ein. Zum Thema Callstacks würde ich empfehlen, die Q-Promise-Bibliothek auszuprobieren, die eine unglaublich fortschrittliche asynchrone Call-Stack-Unterstützung bietet.

+0

Dies ist eine großartige Erklärung dessen, was vor sich geht. Hier ist eine kleine Änderung an Ihrem Code, die auch einen Stacktrace gibt: http://jsfiddle.net/5rHM6/ Leider zeigt der Stack-Trace nicht auf die richtige Zeile (er zeigt auf die console.error-Zeile). Wenn Sie also den Fehler abfangen wollen, ist dies die richtige Antwort. Wenn Sie den Fehler finden wollen, bin ich geneigt, meine Antwort auszuwählen. Es scheint jedoch, dass wenn Sie den Fehler abfangen, die Instrumentierung unterdrückt wird, so dass Sie nicht das Beste aus beiden Welten erhalten können. –

+0

Sie haben recht, es handelt sich eher um einen Nachrichtendienst ("Es gab einen Fehler"), im Gegensatz zu einem vollständigen Fehlerwarndienst mit Stack-Trace. Ich würde Sie dringend bitten, die Q-Bibliothek zu überprüfen, es ist die beste asynchrone Bibliothek, die ich kenne, und sie befassen sich sicherlich mit diesem Problem. –

4

In dojoConfig set useDeferredInstrumentation: true. Hier ist an example.

 <script> 
      var dojoConfig = { 
       useDeferredInstrumentation: true 
      }; 
     </script> 
     <script src="js/lib/dojo/dojo.js.uncompressed.js"></script> 

Dies ergibt eine ziemlich funktionelle Fehlermeldung und stacktrace Ausgang auf console.error:

ReferenceError {} "ReferenceError: FAIL is not defined 
    at http://fiddle.jshell.net/gNdCb/2/show/:25:17 
    at signalListener (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14205:21) 
    at signalWaiting (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14196:4) 
    at resolve (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14360:5) 
    at signalDeferred (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14249:15) 
    at signalListener (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14220:6) 
    at signalWaiting (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14196:4) 
    at resolve (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14360:5) 
    at signalDeferred (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14249:15) 
    at signalListener (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14226:4) 
    ---------------------------------------- 
    rejected at signalDeferred (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14252:15) 
    at signalListener (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14223:5) 
    at signalWaiting (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14196:4) 
    at resolve (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14360:5) 
    at signalDeferred (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14249:15) 
    at signalListener (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14220:6) 
    at signalWaiting (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14196:4) 
    at resolve (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14360:5) 
    at signalDeferred (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14249:15) 
    at signalListener (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14226:4) 
    ---------------------------------------- 
Error 
    at Promise.then.promise.then (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14420:24) 
    at http://fiddle.jshell.net/gNdCb/2/show/:23:13 
    at runFactory (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:1117:43) 
    at execModule (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:1245:5) 
    at http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:812:7 
    at guardCheckComplete (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:1260:5) 
    at contextRequire (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:811:6) 
    at req (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:137:11) 
    at http://fiddle.jshell.net/gNdCb/2/show/:21:1" 
+0

Natürlich wäre es schön, in der Lage zu sein, diese Fehler in etwas wie window.onerror zu fangen oder zu behandeln. Irgendwelche Vorschläge? –

+0

siehe @David McMullins Antwort, um den Fehler zu finden –

0

Ich hatte sehr spezifische Bedürfnisse in diesem benötigt die Ausnahme, um die native Fangklausel zu treffen, die der Browser implementiert. Vergiss es, warum ich brauchte, aber ich verwendet, um etwas wie folgt aus:

function scream(func) { 
    return function() { 
     var args = arguments; 
     setTimeout(function(){ 
      func.apply(null, args); 
     }, 0); 
    }; 
} 

Dann, es zu benutzen

var promise = xhr.get("https://api.github.com/users/octocat/orgs"); 
promise.then(scream(function(data) { 
    //do stuff 
})); 

Durch die Verwendung von setTimeout, können Sie die Funktion auf der Browser-Ereigniswarteschlange ausführen, so dass es unmöglich Dojo, um deine Ausnahme zu verschlucken. Aber im Allgemeinen ist dies eine schlechte Lösung, weil:

  • es Teil des Stack-Trace ändert
  • es einen Teil des Codes ändert die vorherigen synchron asynchron ausgeführt, die das Verhalten des Programms
  • ändern können Sie kann nicht mehrere .then() Objekte mit dem Rückgabewert verknüpfen, was eines der wirklich schönen Dinge über Versprechen ist.

Wie auch immer, ich präsentiere es nur als Option.

Verwandte Themen