Anpassa fel i Nod.js

Javascript är inbyggt i Error ger användbar information, men kan ofta känna brist på tydlighet. One-size-fits-all är bra för språket, men vi kan göra bättre i våra egna appar. Det är där anpassade fel kommer in.

du kan ha sett anpassade fel när du använder Node.js. Nodens inbyggda feltyper som AssertionError, RangeError, ReferenceError, SyntaxError, och SystemError är alla tillägg av den ursprungliga klassen Error.

att använda Error som bas ger dig all kraft i Javascript-implementeringen plus ytterligare fördelar. Här är bara några:

  • anpassade felmeddelandeformat.
  • ytterligare egenskaper på Felobjektet.
  • namngivna fel för att underlätta felsökning och villkorlig felhantering.
  • konsekventa fel för bibliotekskonsumenter att referera till.

utöka felklassen

för att komma igång, låt oss använda ett generiskt exempel. Vi kommer att förlänga klassen Error och använda super för att ärva dess funktioner.

class CustomError extends Error { constructor(...params) { super(...params) // We're spreading `params` as a way to bring all of `Error`'s functionality in. }}

nu, när du throw ett fel kan du göra det med throw new CustomError("Something went wrong..."). Det ger dig också möjlighet att kontrollera fel mot typen:

try { throw new CustomError("Something went wrong")} catch (error) { if (error instance of CustomError) { // do something specifically for that type of error }}

detta ensam gör inte mycket, annat än att ge dig en ny feltyp att ringa och kontrollera. För att bättre förstå vad som kan göras, låt oss titta på vad som kommer standard på Error.

  • Error.name
  • Fel.meddelande
  • fel.prototypstadiet.toString ()
  • fel.prototypstadiet.constructor()

inte mycket att jobba med finns det? Bortsett från konstruktören och toString – metoden är namnet på felet och meddelandet som beskriver felet de enda delarna som vi sannolikt kommer att använda. I exemplet ovan ställs message in genom att skicka ”något gick fel” som argument när du instanserar felet.

lyckligtvis, de flesta javascript-plattformar som webbläsaren och noden.js har lagt till sina egna metoder och egenskaper ovanpå de listade. Vi kommer att fokusera på några aspekter av felimplementeringen från V8, Javascript-motorn som driver Chrome och Node.js.

de två intresseområdena är stackoch captureStackTrace. Som deras namn antyder, de tillåter dig att ytan stack spår. Låt oss se hur det ser ut med ett exempel.

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)}

i det här exemplet ringer vi Error.captureStackTrace, om plattformen stöder det, för att säkerställa att ett fullständigt spår läggs till i vårt anpassade fel. Vi throw felet från try – blocket, som kommer att överföra kontrollen till catch – blocket.

om du kör koden ovan ser du att den första raden i stack är felet name och message.

Our Custom Error: Something went wrong

detta fel är inte särskilt ”djupt”, så stacken är mestadels nod.JS internals. Varje rad är en” ram ” av stapeln. De innehåller detaljer om platsen för felet i kodbasen.

nu när vi vet hur man gör och ringer ett anpassat fel, låt oss göra det användbart.

anpassa Felinnehåll

det anpassade felet vi har arbetat med är bra, men låt oss ändra det för att göra det mer användbart. Klassen kommer att vara CircuitError. Vi använder den för att tillhandahålla anpassade fel som kommer från en brytare. Om du inte är bekant med mönstret är det okej. Implementeringsdetaljerna för strömbrytaren är inte viktiga. Det som är viktigt är att vi kan skicka lite information till felet, och det kommer att presentera den informationen för användaren.

en brytare har ett ”öppet” tillstånd som inte tillåter något att passera genom det under en fast tid. Låt oss ställa in vår CircuitError för att innehålla några detaljer som kan vara användbara för de funktioner som tar emot den när staten är OPEN.

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.` } }}

vårt uppdaterade fel gör några nya saker, allt inom konstruktören. De godkända argumenten har ändrats (1) för att inkludera brytarens state, samt en nextAttempt tidsstämpel för att indikera när brytaren börjar försöka begära igen.

det ställer sedan in några nya egenskaper och uppdaterar meddelandet beroende på de presenterade värdena. Vi kan testa det genom att kasta en ny version av detta fel.

try { throw new CircuitError("OPEN", Date.now() + 8000)} catch (err) { console.error(err)}

nu när vi kastar felet tar det staten som det första argumentet och en tidsstämpel som den andra. För denna demo vi passerar i tiden 8000 millisekunder i framtiden. Lägg märke till att vi också loggar själva felet, snarare än bara stacken.

att köra koden kommer att resultera i något som följande:

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}

resultatet är felnamnet följt av meddelandet på första raden. Sedan har vi resten av stacken, följt av alla egenskaper som vi har satt i CircuitError. Våra konsumenter av detta fel kan använda den informationen för att reagera på felet. Till exempel:

try { throw new CircuitError("OPEN", Date.now() + 8000)} catch (err) { customLogger(err) if (err.state === "OPEN") { handleOpenState(err.nextAttempt) }}

istället för ett generiskt fel har vi nu något som passar bättre för behoven i vår applikation.

reagera på fel

anpassade fel är ett bra sätt att reagera på fel. Det är vanligt att anta att alla fel är oväntade, men genom att tillhandahålla användbara fel kan du göra deras existens lättare att hantera. Genom att använda anpassade fel kan vi inte bara förse användare av våra applikationer med värdefull data, men vi presenterar också möjligheten att svara på feltyper genom instance of – tillståndet.

på bärare, vi använder anpassade fel för att standardisera svar i vår kod, ger bara den information du behöver i vår klient, och göra våra fel åtgärds.

Hur använder du anpassade fel i dina applikationer? Anslut med oss @BearerSH och låt oss veta.

Lämna ett svar

Din e-postadress kommer inte publiceras.