Javascript ‘ s ingebouwde Error
biedt nuttige informatie, maar kan vaak het gevoel gebrek aan duidelijkheid. One-size-fits-all is geweldig voor de taal, maar we kunnen het beter doen in onze eigen apps. Daar komen aangepaste fouten bij kijken.
u hebt mogelijk zelfgemaakte fouten gezien bij het gebruik van Node.js. Node is gebouwd in fouttypen zoals AssertionError
, RangeError
, ReferenceError
, SyntaxError
, en SystemError
zijn alle uitbreidingen van de oorspronkelijke Error
klasse.
het gebruik van Error
als basis geeft u alle kracht van Javascript ‘ s implementatie plus extra voordelen. Hier zijn slechts een paar:
- aangepaste foutmeldingen.
- aanvullende eigenschappen op het Foutobject.
- genoemde fouten om debuggen en voorwaardelijke foutafhandeling gemakkelijker te maken.
- consistente fouten voor bibliotheekgebruikers om te verwijzen.
uitbreiding van de Foutklasse
om te beginnen gebruiken we een algemeen voorbeeld. We zullen de klasse Error
uitbreiden en super
gebruiken om de functies ervan te erven.
class CustomError extends Error { constructor(...params) { super(...params) // We're spreading `params` as a way to bring all of `Error`'s functionality in. }}
wanneer u throw
een fout maakt, kunt u dit doen met throw new CustomError("Something went wrong...")
. Het geeft je ook de mogelijkheid om fouten te controleren tegen het type:
try { throw new CustomError("Something went wrong")} catch (error) { if (error instance of CustomError) { // do something specifically for that type of error }}
dit alleen doet niet veel, behalve het geven van een nieuw fouttype om op te bellen en te controleren. Om beter te begrijpen wat er gedaan kan worden, Laten we eens kijken naar wat standaard is op Error
.
- Error.name
- Fout.bericht
- fout.prototype.toString ()
- fout.prototype.constructeur()
niet veel om mee te werken, hè? Afgezien van de constructor en de toString
methode, zijn de naam van de fout en het bericht dat de fout beschrijft de enige delen die we waarschijnlijk zullen gebruiken. In het voorbeeld hierboven wordt message
ingesteld door “er is iets fout gegaan” als argument te geven bij het instantiëren van de fout.
gelukkig zijn de meeste javascript platforms zoals de browser en Node.js hebben hun eigen methoden en eigenschappen toegevoegd op de top van de genoemde. We zullen ons richten op een paar aspecten van de fout implementatie van V8, de Javascript-engine voeden Chrome en Node.js.
de twee aandachtsgebieden zijn stack
en captureStackTrace
. Zoals hun namen suggereren, laten ze je de stack trace aan de oppervlakte komen. Laten we eens kijken hoe dat eruit ziet met een voorbeeld.
class CustomError extends Error { constructor(...args) { super(...args) if (Error.captureStackTrace) { Error.captureStackTrace(this, CustomError) } this.name = "Our Custom Error" }}try { throw new CustomError("Something went wrong")} catch (err) { console.error(err.stack)}
in dit voorbeeld roepen we Error.captureStackTrace
aan, als het platform het ondersteunt, om er zeker van te zijn dat een volledig spoor wordt toegevoegd aan onze aangepaste fout. We dan throw
de fout van binnen het try
blok, die de controle zal doorgeven aan het catch
blok.
als u de bovenstaande code uitvoert, zult u zien dat de eerste regel van stack
de fout name
en message
is.
Our Custom Error: Something went wrong
deze fout is niet erg “diep”, dus de stack is meestal knooppunt.js internals. Elke regel is een “frame” van de stack. Ze bevatten details over de locatie van de fout in de codebase.
nu we weten hoe een aangepaste fout te maken en aan te roepen, laten we het nuttig maken.
aangepaste fout inhoud
de aangepaste fout waarmee we hebben gewerkt is prima, maar laten we het veranderen om het nuttiger te maken. De klasse wordt CircuitError
. We gebruiken het om aangepaste fouten te maken die van een stroomonderbreker komen. Als je het patroon niet kent, is dat oké. De implementatie details van de stroomonderbreker zijn niet belangrijk. Wat belangrijk is, is dat we wat informatie in de fout kunnen doorgeven, en het zal die informatie aan de gebruiker presenteren.
een breaker heeft een” OPEN ” status die niet toestaat dat er gedurende een bepaalde tijd iets doorheen gaat. Laten we onze CircuitError
zo instellen dat het enkele details bevat die nuttig kunnen zijn voor de functies die het ontvangen wanneer de status OPEN
is.
class CircuitError extends Error { // 1 constructor(state, nextAttempt, ...params) { super(...params) if (Error.captureStackTrace) { Error.captureStackTrace(this, CircuitError) } this.name = "CircuitError" this.state = state // 2 this.message = `The Circuit is ${state}.` // 3 if (nextAttempt) { this.timestamp = Date.now() this.nextAttempt = nextAttempt this.message += ` Next attempt can be made in ${this.nextAttempt - this.timestamp}ms.` } }}
onze bijgewerkte fout doet een paar nieuwe dingen, allemaal binnen de constructor. De argumenten zijn gewijzigd (1) om de state
van de stroomonderbreker te bevatten, evenals een nextAttempt
tijdstempel om aan te geven wanneer de stroomonderbreker opnieuw verzoeken zal proberen.
het stelt dan een paar nieuwe eigenschappen in en werkt het bericht bij afhankelijk van de gepresenteerde waarden. We kunnen het testen door het gooien van een nieuwe versie van deze fout.
try { throw new CircuitError("OPEN", Date.now() + 8000)} catch (err) { console.error(err)}
als we nu de fout gooien, neemt het de status als het eerste argument en een tijdstempel als de tweede. Voor deze demo passeren we in de toekomst 8000 milliseconden in de tijd. Merk op dat we ook de fout zelf registreren, in plaats van alleen de stack.
het uitvoeren van de code zal resulteren in iets als het volgende:
CircuitError : The Circuit is OPEN. Next attempt can be made in 6000ms. at Object.<anonymous> (/example.js:21:9) at Module._compile (internal/modules/cjs/loader.js:1063:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1103:10) at Module.load (internal/modules/cjs/loader.js:914:32) at Function.Module._load (internal/modules/cjs/loader.js:822:14) at Function.Module.runMain (internal/modules/cjs/loader.js:1143:12) at internal/main/run_main_module.js:16:11 { name: 'Circuit Error', state: 'OPEN', message: 'The Circuit is OPEN. Next attempt can be made in 6000ms.', timestamp: 1580242308919, nextAttempt: 1580242314919}
het resultaat is de foutnaam gevolgd door het bericht op de eerste regel. Dan hebben we de rest van de stack, gevolgd door alle eigenschappen die we hebben ingesteld in de CircuitError
. Onze gebruikers van deze fout kunnen die gegevens gebruiken om op de fout te reageren. Bijvoorbeeld::
try { throw new CircuitError("OPEN", Date.now() + 8000)} catch (err) { customLogger(err) if (err.state === "OPEN") { handleOpenState(err.nextAttempt) }}
in plaats van een algemene fout, hebben we nu iets beter aangepast aan de behoeften van onze toepassing.
reageren op fouten
aangepaste fouten zijn een geweldige manier om op fouten te reageren. Het is gebruikelijk om aan te nemen dat alle fouten zijn onverwacht, maar door het verstrekken van nuttige fouten kunt u hun bestaan gemakkelijker te hanteren. Door gebruik te maken van aangepaste fouten, kunnen we niet alleen gebruikers van onze applicaties voorzien van waardevolle gegevens, maar presenteren we ook de mogelijkheid om te reageren op fouttypen door middel van de instance of
voorwaarde.
bij Toonder gebruiken we aangepaste fouten om reacties in onze code te standaardiseren, alleen de informatie te verstrekken die u nodig hebt in onze klant, en om onze fouten uitvoerbaar te maken.
Hoe gebruikt u aangepaste fouten in uw toepassingen? Maak contact met ons @BearerSH en laat het ons weten.