2015-01-17 16 views
53

Czy istnieje sposób na globalne wychwycenie wszystkich wyjątków, w tym wyjątków od obietnicy. Przykład:Jak wychwycić niezatapiany wyjątek w obietnicy

window.onerror = function myErrorHandler(errorMsg, url, lineNumber) { 
     alert("Error occured: " + errorMsg);//or any message 
     return false; 
    } 

    var myClass = function(){ 

    } 


    var pr = new Promise(function(resolve, react){ 
     var myInstance = new myClass(); 
     myInstance.undefinedFunction(); // this will throw Exception 
     resolve(myInstance); 
    }); 


    pr.then(function(result){ 
     console.log(result); 
    }); 

    // i know right will be this: 
    // pr.then(function(result){ 
    //  console.log(result); 
    // }).catch(function(e){ 
    //  console.log(e); 
    // }); 

Ten skrypt cicho ginie bez błędu. Nic w ogniu.

Moje pytanie brzmi: jeśli popełnię błąd i zapomniałem go złapać, czy istnieje sposób, aby go złapać globalnie?

Odpowiedz

15

Większość implementacji obietnica obecnie nie zapewniają rodzaj funkcjonalności masz na myśli, ale liczba bibliotek 3rd-Party obietnica (w tym Q i bluebird) zapewnić done() metodę, która będzie złapać i przekaż żadnych niezłapane błędów, a tym samym wyprowadzanie ich na konsolę.

(Edit: patrz odpowiedź Benjamin Gruenbaum na temat funkcji Bluebird przy rozpatrywaniu niezłapane wyjątkami)

Więc jeśli masz to, że po prostu trzeba postępować zgodnie z zasada, że ​​każda obietnica używasz powinny być albo zwrócone lub zakończony .done():

pr.then(function(result){ 
    console.log(result); 
}) 
.done(); 

zacytować odniesienia P API

Złota zasada done kontra then użycie: albo return twoja obietnica wobec kogoś innego, albo jeśli łańcuch się kończy, zadzwoń na done, aby to zakończyć. Kończenie z catch jest niewystarczające, ponieważ program obsługi catch może sam rzucić błąd.

Zdaję sobie sprawę, że to nadal wymaga trochę więcej pracy i nadal można zapomnieć, aby to zrobić, ale jest to poprawa w stosunku do konieczności .catch() i jawnie obsłużyć każdy błąd, zwłaszcza z tego powodu wskazane powyżej.

+0

Dziękuję, będę badanie Q na pierwszy :-) – John

+2

Właściwie sporządzona jest nie różni od po prostu robi '.catch (miotacz)' (lub robi to samo ze skrótu na przykład dodanie 'Promise.prototype .done = ... '. Więc jest to bezcelowe w tym celu, szczególnie w bluebird gdzie normalnie zgłaszane są niepoprawne błędy – Esailija

+1

@Eailailija Czy możesz rozwinąć ten temat? Co w takim razie byłoby" throwerem "? – JLRishe

16

Update, rodzime obiecuje teraz wykonać następujące czynności w większości przeglądarek:

window.addEventListener("unhandledrejection", function(err, promise) { 
    // handle error here, for example log 
}); 

Byliśmy po prostu dyskutować to na drugi dzień.

Oto jak chcesz to zrobić z Bluebird:

window.onpossiblyunhandledexception = function(){ 
    window.onerror.apply(this, arguments); // call 
} 

window.onerror = function(err){ 
    console.log(err); // logs all errors 
} 

Z Bluebird jest to również możliwe użycie Promise.onPossiblyUnhandledRejection. Wywołania dla done nie są potrzebne, ponieważ biblioteka wykryje nieobsłużone odrzucenie w przeciwieństwie do Q (UPDATE 2016 - teraz napisałem kod dla Q i robi to).

chodzi o rodzime obietnic - one będzie ostatecznie zgłosić do obu window.onerror lub nowego procesu obsługi, ale specyfikacja nie jest jeszcze zrobione - można follow it here.

0

Jeśli używasz natywnej obietnicy, jest to całkiem proste.
Musisz tylko .catch odrzucić niektóre miejsca.

ajax(request).catch(function(rejected){ 
     console.log(rejected); 
}); 

Jeśli nie złapię go gdzieś, niezatrzymana obietnica będzie się wyświetlać. Ale Jeśli złapię go gdzieś ...

+5

To nie odpowiada na pytanie. – csauve

3

W node.js, można użyć:

process.on('unhandledRejection', (reason, promise) => { 
    console.error(`Uncaught error in`, promise); 
}); 
+0

Jest to użyteczne podczas debugowania w nieznanym, ale jeśli wiesz, która obietnica i masz dostęp, powinieneś użyć '.catch' lub' .done' dla lepszej łatwości konserwacji – tsuz

+0

W nowszej wersji Node jest to standardowe zachowanie. Zatem błędy w niezaspokojonych obietnicach będą rejestrowane, nawet bez dodawania tego fragmentu kodu. – JussiR

2

Jeśli kod, który może być wykonywany zarówno w przeglądarce & w node.js pisania środowisko, można owinąć kod w samodzielnym wykonywaniu funkcji tak:

var isNode = (typeof process !== 'undefined' && typeof process.on !== 'undefined'); 
(function(on, unhandledRejection) { 
    // PUT ANY CODE HERE 
    on(unhandledRejection, function(error, promise) { 
     console.error(`Uncaught error in`, promise); 
    }); 
    // PUT ANY CODE HERE 
})(
    isNode ? process.on.bind(process) : window.addEventListener.bind(window), 
    isNode ? "unhandledRejection" : "unhandledrejection" 
); 

Co by się stało, jeśli użyć tego kodu:

  • Jeśli uruchomisz go w środowisku Node.js, twój program obsługi zostanie dołączony do obiektu procesu i zostanie wykonany, gdy w obietnicy znajdziesz nieprzechwycony wyjątek.

  • Gdybyś go uruchomić w środowisku przeglądarki, Twój handler będzie dołączony do obiektu window i być wykonywane, gdy masz przechwycony wyjątek w obietnicy i przeglądarka obsługuje zdarzenie unhandledrejection.

  • Gdybyś go uruchomić w środowisku przeglądarki bez wsparcia dla unhandledrejection, nie będzie w stanie złapać przechwycony wyjątek i swoją obsługi unhandledrejection zdarzenia nigdy nie zostanie uruchomiony, ale nie dostanie żadnych błędów, jeśli istnieje bez nieprzytomnych wyjątków.

Powiązane problemy