Tilpasning af fejl i Node.JS

Javascript er indbygget Error giver nyttige oplysninger, men kan ofte føle sig manglende klarhed. En-størrelse-passer-alle er fantastisk til sproget, men vi kan gøre det bedre i vores egne apps. Det er her brugerdefinerede fejl kommer ind.

du har muligvis set brugerdefinerede fejl, når du bruger Node.js. Node er bygget i fejltyper som AssertionError, RangeError, ReferenceError, SyntaxError, og SystemError er alle udvidelser af den indfødte Error klasse.

brug af Error som base giver dig al kraften i Javascript ‘ s implementering plus yderligere fordele. Her er blot nogle få:

  • brugerdefinerede fejlmeddelelsesformater.
  • yderligere egenskaber på Fejlobjektet.
  • navngivne fejl for at gøre fejlfinding og betinget fejlhåndtering lettere.
  • konsistente fejl for bibliotekets forbrugere at henvise til.

udvidelse af Fejlklassen

for at komme i gang, lad os bruge et generisk eksempel. Vi vil udvide Error klassen og bruge super til at arve dens 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 throwen fejl, kan du gøre det med throw new CustomError("Something went wrong..."). Det giver dig også mulighed for at kontrollere fejl mod typen:

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

dette alene gør ikke meget, bortset fra at give dig en ny fejltype at ringe og tjekke for. For bedre at forstå, hvad der kan gøres, lad os se på, hvad der kommer standard på Error.

  • Error.name
  • Fejl.meddelelse
  • fejl.prototype.toString ()
  • fejl.prototype.konstruktør()

ikke meget at arbejde med er der? Bortset fra konstruktøren og toString – metoden er navnet på fejlen og meddelelsen, der beskriver fejlen, de eneste dele, som vi sandsynligvis vil bruge. I eksemplet ovenfor er message indstillet ved at passere” noget gik galt ” som argumentet ved instantiering af fejlen.

heldigvis er de fleste javascript-platforme som bro.ser og Node.js har tilføjet deres egne metoder og egenskaber oven på dem, der er anført. Vi vil fokusere på et par aspekter af Fejlimplementeringen fra V8, Javascript-motoren, der driver Chrome og Node.js.

de to interesseområder er stackog captureStackTrace. Som deres navne antyder, de giver dig mulighed for at overflade stakken spor. Lad os se, hvordan det ser ud med et eksempel.

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 dette eksempel kalder vi Error.captureStackTrace, hvis platformen understøtter det, for at sikre, at der tilføjes et komplet spor til vores brugerdefinerede fejl. Vi så throw fejlen fra try blokken, som vil passere kontrol til catch blokken.

hvis du kører koden ovenfor, vil du se, at den første linje i stack er fejlen nameog message.

Our Custom Error: Something went wrong

denne fejl er ikke særlig “dyb”, så stakken er for det meste Node.JS internals. Hver linje er en” ramme ” af stakken. De indeholder detaljer om placeringen af fejlen i kodebasen.

nu hvor vi ved, hvordan vi laver og kalder en brugerdefineret fejl, lad os gøre det nyttigt.

tilpasning af Fejlindhold

den brugerdefinerede fejl, vi har arbejdet med, er fint, men lad os ændre det for at gøre det mere nyttigt. Klassen vil være CircuitError. Vi bruger det til at levere brugerdefinerede fejl, der kommer fra en afbryder. Hvis du ikke er bekendt med mønsteret, er det okay. Implementeringsoplysningerne for afbryderen er ikke vigtige. Det vigtige er, at vi kan videregive nogle oplysninger til fejlen, og det vil præsentere disse oplysninger for brugeren.

en breaker har en “åben” tilstand, der ikke tillader noget at passere igennem det i et fast tidsrum. Lad os indstille vores CircuitError op til at indeholde nogle detaljer, der kan være nyttige for de funktioner, der modtager det, når staten er 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.` } }}

vores opdaterede fejl gør et par nye ting, alt sammen inden for konstruktøren. Argumenterne bestået har ændret (1) til at omfatte state af afbryderen, samt en nextAttempt tidsstempel for at angive, hvornår afbryderen vil begynde at prøve anmodninger igen.

det indstiller derefter et par nye egenskaber og opdaterer meddelelsen afhængigt af de præsenterede værdier. Vi kan teste det ved at kaste en ny version af denne fejl.

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

nu når vi kaster fejlen, tager den staten som det første argument og et tidsstempel som det andet. Til denne demo passerer vi 8000 millisekunder i fremtiden. Bemærk, at vi også logger fejlen selv, snarere end blot stakken.

kørsel af koden vil resultere i noget som følgende:

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 er fejlnavnet efterfulgt af meddelelsen på første linje. Så har vi resten af stakken, efterfulgt af alle de egenskaber, vi har angivet i CircuitError. Vores forbrugere af denne fejl kunne bruge disse data til at reagere på fejlen. For eksempel:

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

i stedet for en generisk fejl har vi nu noget, der passer bedre til vores applikations behov.

reaktion på fejl

brugerdefinerede fejl er en fantastisk måde at reagere på fejl. Det er almindeligt at antage, at alle fejl er uventede, men ved at give nyttige fejl kan du gøre deres eksistens lettere at håndtere. Ved at gøre brug af brugerdefinerede fejl kan vi ikke kun give brugere af vores applikationer værdifulde data, men vi præsenterer også muligheden for at reagere på fejltyper gennem instance of – tilstanden.

hos Bearer bruger vi brugerdefinerede fejl til at standardisere svar i vores kode, give lige de oplysninger, du har brug for i vores klient, og gøre vores fejl Handlingsrettede.

Hvordan bruger du brugerdefinerede fejl i dine applikationer? Slut med os @BearerSH og lad os vide.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.