Try catch i Node.js: slik håndterer du feil uten å krasje hele appen

Mange som starter med Node.js opplever det samme problemet: alt virker helt fint helt til én ting går galt, og hele programmet stopper. God feilhåndtering handler ikke bare om å «fikse feil», men om å bygge kode som tåler virkeligheten.
I denne artikkelen ser vi på hvordantry/catchfungerer i Node.js, hva som er forskjellen på synkrone og asynkrone feil, og hvordan du kan strukturere koden slik at du lettere finner og håndterer problemer.
Hva try og catch faktisk gjør
try/catcher en måte å fange opp feil (exceptions) som ellers ville stoppet programmet. Koden itry-blokken kjøres som normalt, men hvis noe kaster en feil, hopper kjøringen rett tilcatch-blokken.
Et enkelt eksempel i Node.js kan se slik ut:
Eksempel:
function parseJson(text) {
try {
const data = JSON.parse(text);
return data;
} catch (err) {
console.error('Klarte ikke å tolke JSON:', err.message);
return null;
}
}
Her sikrer vi at en ugyldig JSON-streng ikke krasjer hele programmet, men i stedet logges og gir en kontrollert returverdi.
Synkron vs asynkron: den viktigste fellen
try/catch fungerer bare direkte på synkron kode. Det vil si kode som kjører fortløpende i samme kallstakk, som funksjonskall, beregninger og JSON.parse. Med en gang du bruker callbacks, tidsur eller promises, er du i asynkron verden.
Dette fungerer:
try {
const result = riskySyncOperation();
} catch (err) {
console.error('Feil skjedde:', err);
}
Mens dette ikke fanger feilen:
try {
setTimeout(() => {
throw new Error('Oops');
}, 1000);
} catch (err) {
// Kommer aldri hit
}
Feilen kastes i en annen «runde» av hendelsessløyfen, så try/catch rundt setTimeout ser aldri feilen.
Feilhåndtering med callbacks
Mye eldre eller lavnivå Node-kode bruker callback-mønsteret der første argument er en feil (ofte kalterr). Her er ikke try/catch verktøyet du bruker, men konseptet «error-first callback».
Eksempel med fs.readFile:
const fs = require('fs');
fs.readFile('data.json', 'utf8', (err, data) => {
if (err) {
console.error('Klarte ikke å lese filen:', err);
return;
}
try {
const parsed = JSON.parse(data);
console.log('Leser data:', parsed);
} catch (parseErr) {
console.error('Ugyldig JSON:', parseErr.message);
}
});
Legg merke til atfilfeilhåndteres viaerri callbacken, mensJSON-feilener synkron og derfor håndteres med try/catch inne i callbacken.
try/catch sammen med async og await
Med promises ogasync/awaitblir try/catch plutselig mye mer nyttig igjen. Når du brukerawait, ser asynkron kode nesten ut som synkron, og exceptions i et promise kan fanges i try/catch.
Eksempel med fetch-lignende funksjon:
async function fetchUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`);
if (!response.ok) {
throw new Error('HTTP-feil: ' + response.status);
}
return response.json();
}
async function main() {
try {
const user = await fetchUser(123);
console.log('Fant bruker:', user);
} catch (err) {
console.error('Klarte ikke å hente bruker:', err.message);
}
}
Her fanger try/catch både nettverksfeil, HTTP-feil vi selv kaster, og eventuelle andre exceptions som oppstår i fetchUser eller i await-linjen.
Typiske mønstre for tryggere Node.js-kode

For å unngå rotete feilhåndtering lønner det seg å bruke noen faste mønstre. Et nyttig grep er å samle asynkron logikk i små async-funksjoner og gi hver funksjon ett tydelig ansvar.
Eksempel med «service»-funksjoner:
async function loadConfig(path) {
try {
const data = await fs.promises.readFile(path, 'utf8');
return JSON.parse(data);
} catch (err) {
// Legg til kontekst
throw new Error('loadConfig feilet for ' + path + ': ' + err.message);
}
}
Når du senere kaller loadConfig, kan du fange feilen høyere i systemet og fortsatt ha nyttig informasjon om hva som skjedde.
Hvor bør du bruke try/catch, og hvor bør du la feilen gå videre?
En vanlig misforståelse er at «god feilhåndtering» betyr å fange absolutt alle feil overalt. Ofte er det bedre å la feil boble opp til et lag som vet hva som er en fornuftig reaksjon: vise feilmelding, returnere 500-status eller avslutte programmet kontrollert.
Et enkelt beslutningsgrunnlag kan være:
- Bruk try/catch der du kangjøre noe fornuftigmed feilen, som å prøve på nytt eller gi en tydelig respons til klienten.
- La feilen gå videre hvis du bare kan logge den uten å ta en beslutning. Høyere nivå i koden har ofte mer kontekst.
- Ikke svelg feil stille. Hvis du må ignorere noe, dokumenter hvorfor med en tydelig kommentar.
Global feilhåndtering: siste sikkerhetsnett
Selv med god struktur vil noen feil slippe gjennom. Node.js tilbyr globale hendelser som kan brukes som siste sikkerhetsnett, men de bør brukes med varsomhet.
Et typisk oppsett kan være:
process.on('uncaughtException', (err) => {
console.error('Ufanget feil:', err);
// Ofte lurt å avslutte prosessen kontrollert her
});
process.on('unhandledRejection', (reason, promise) => {
console.error('Ubehandlet promise-avvisning:', reason);
});
Dette bør ikke være hovedstrategien din for feilhåndtering, men det kan hjelpe deg å oppdage problemer tidlig i utvikling eller logge kritiske feil før programmet stoppes.
Små vaner som gjør feilsøking mye enklere
Noen enkle vaner kan gjøre stor forskjell når noe faktisk går galt. Først og fremst: logghele feilen, ikke bare err.message. Hele objektet inneholder som regel stack trace og mer kontekst.
I tillegg kan du:
- Gi egne feiltyper eller meldinger som forklarer hva du forsøkte å gjøre, ikke bare hva som gikk galt teknisk.
- Bruke konsistent struktur på feilmeldinger, for eksempel prefiks med funksjonsnavn eller modul.
- Teste feiltilfeller bevisst, for eksempel ved å bruke ugyldige input-data eller simulere nedetid på en tjeneste.
Over tid bygger du opp en kodebase der nye feil er raskere å forstå, og der try/catch brukes målrettet i stedet for tilfeldig.









0 kommentarer