2012-07-31 3 views
8

Per la segnalazione degli errori, vorrei inserire un wrapper try-catch attorno al codice di ogni funzione che ho.C'è un modo per aggiungere try-catch ad ogni funzione in Javascript?

Quindi, fondamentalmente voglio sostituire

function foo(arg){ 
    bar(); 
} 

... con ...

function foo(arg){ 
    try { 
     bar() 
    } 
    catch(e){ 
     customErrorHandler(e) 
    } 
} 

Esiste un modo per applicare questa generica cosa try-catch a tutte le funzioni senza modificare manualmente tutti di loro? Ad esempio modificando il prototipo dell'oggetto Function?

EDIT

Perché voglio provare-cattura tutte le mie funzioni: Sto costruendo un app HTML5 che sto pubblicando su iOS e Android. Posso dire dal mio rudimentale errore javascript corrente che, anche se l'app funziona correttamente sul mio dispositivo, gli errori si verificano su altri dispositivi.

Il mio obiettivo è duplice: ogni volta che si verifica un errore javascript dispositivo di qualcuno ...

  1. voglio informare l'utente che l'applicazione potrebbe non funzionare perfettamente
  2. Voglio sapere approssimativamente dove l'errore si è verificato, quindi so dove guardare per il problema
+1

No - si può semplicemente racchiudere l'invocazione * della funzione * in un try-catch, ma non i suoi contenuti se la funzione in realtà non contiene un try-catch. Per quello che vale, ricoprire il tuo codice con le dichiarazioni try-catch è una pessima idea. Se c'è un errore, dovresti risolverlo, non permetterlo, ma sopprimerlo tramite try-catch. – Utkanos

+2

+1 per voler provare correttamente a catturare tutte le tue funzioni. Tuttavia, penso che dovrai modificarli tutti manualmente. – Limey

+1

Il tentativo di cattura è molto costoso. Sei sicuro di volerlo fare? Qual è il requisito? –

risposta

9

Questo non è semplice poiché non è possibile trovare tutte le funzioni JavaScript definite ovunque. Ad esempio, un tale approccio probabilmente mancherebbe le funzioni di callback definite in fase di esecuzione.

Probabilmente non si desidera includere tutte le funzioni perché includerebbe funzioni e funzioni del browser da librerie JavaScript che sicuramente non si desidera includere.

Un approccio molto migliore è probabilmente quello di definire una funzione che avvolge un'altra funzione:

var tcWrapper = function(f) { 
    return function() { 
     try { 
      f.apply(this, arguments); 
     } catch(e) { 
      customErrorHandler(e) 
     } 
    } 
} 

Ora è possibile utilizzare questa funzione per decorare tutto ciò che si desidera.Wrapping diventerà più semplice se si utilizzano gli spazi dei nomi:

var NS = { f: function(...) { ... } } 

Basta mettere tutte le funzioni di avvolgere in un namespace speciale e poi iterare lo spazio dei nomi:

$.each(NS, function(i,n) { 
    var p = NS[n]; 
    if(typeof p === 'function') { 
     NS[n] = tcWrapper(p); 
    } 
}); 
+0

Non tutte le funzioni vorranno lo stesso 'questo'. Potresti essere consapevole di quale "questo" stai inviando. Ad esempio, i gestori di eventi a volte ottengono che questo sia il target dell'evento, o metodi oggetto. Puoi comunque eseguire il loop sulle proprietà degli oggetti e sostituirli con un getter (con Object.defineProperty) che li avvolge in una funzione inline che potrebbe sia risolverli a un valore che non può essere manomesso dall'esterno, sia come wrapping loro in un blocco di prova. – nus

+0

@nus: Non vedo il tuo punto. Ho appena passato "questo" ma forse lo sto facendo male? Forse le tue informazioni sono troppo complesse per un commento. Che ne dici di mostrarci il codice e le ragioni in un'altra risposta? –

+0

Mi dispiace, il mio errore non è riuscito a vedere l'applicazione viene eseguita solo quando la funzione restituita è già collegata a NS. In qualche modo ho pensato che venisse chiamato nel contesto di tcpWrapper, nel qual caso avrebbe risolto 'questo' da tcpWrapper su ogni funzione. – nus

1

Va bene, mi sembra di aver trovato qui: http://www.nczonline.net/blog/2009/04/28/javascript-error-handling-anti-pattern/

in sostanza, tutte le funzioni sono sostituite da un wrapper try-catch con la funzione originale nella parte try.

+6

Il titolo del post del blog dice che è un anti-pattern, cioè possibile ma sconsigliabile. Fino a voi, ma davvero non penso che sia una buona idea. – Utkanos

+1

I post del blog parlano di anti-pattern ma mostrano anche soluzioni. –

-3

Mi chiedo (questa è pura speculazione, quindi non so se questo dovrebbe funzionare) si potrebbe fare qualcosa di simile:

function callTryCatch(functionSignature) { 
    try { 
     eval(functionSignature); 
    } catch (e) { 
     customErrorHandler(e); 
    } 
} 

function entryPoint() { 
    callTryCatch(function() { 
     // do function logic 
    }); 
} 

Ancora una volta, questa è pura speculazione e non ho ancora testato, ma se è ancora possibile penso che la chiave si trova nella dichiarazione eval.

+3

Non usare mai 'eval'; nel tuo caso, 'apply()' fa quello che vuoi. –

0

avevo bisogno di andare fortificare po 'di codice, così ho scritto una funzione chiamata fortify e l'ho inserita in un modulo NPM. È un lavoro in corso, ma dovrebbe aiutare.

https://github.com/infinitered/over-armour

Bonus: funziona con le funzioni asincrone. Feedback welcome

Problemi correlati