Sök…
Syntax
- försök {…} fånga (fel) {…}
- försök {...} äntligen {...}
- försök {...} fånga (fel) {...} äntligen {...}
- kasta nytt fel ([meddelande]);
- kasta fel ([meddelande]);
Anmärkningar
try
låter dig definiera ett kodblock som ska testas för fel medan det körs.
catch
låter dig definiera ett kodblock som ska köras, om ett fel inträffar i try
.
finally
kan du köra kod oavsett resultat. Var dock försiktig, kontrollflödesanalyserna för try and catch-block kommer att avbrytas tills genomförandet av det slutliga blocket är slut.
Interaktion med löften
Undantag är att synkronisera kod vad avslag är att lova baserad asynkron kod. Om ett undantag kastas i en löftehandlare, kommer dess fel automatiskt att fångas och användas för att avvisa löfte istället.
Promise.resolve(5)
.then(result => {
throw new Error("I don't like five");
})
.then(result => {
console.info("Promise resolved: " + result);
})
.catch(error => {
console.error("Promise rejected: " + error);
});
Promise rejected: Error: I don't like five
Förslaget om asyncfunktioner - som förväntas vara en del av ECMAScript 2017 - utvidgar detta i motsatt riktning. Om du väntar på ett avvisat löfte tas felet upp som ett undantag:
async function main() {
try {
await Promise.reject(new Error("Invalid something"));
} catch (error) {
console.log("Caught error: " + error);
}
}
main();
Caught error: Invalid something
Felobjekt
Runtime-fel i JavaScript är exempel på Error
. Error
kan också användas som det är eller som bas för användardefinierade undantag. Det är möjligt att kasta alla typer av värde - till exempel strängar - men du uppmanas starkt att använda Error
eller ett av dess derivat för att säkerställa att felsökningsinformation - som stapelspår - är korrekt bevarad.
Den första parametern till Error
är det meddelandet som kan läsas av människor. Du bör försöka alltid ange ett användbart felmeddelande om vad som gick fel, även om ytterligare information kan hittas någon annanstans.
try {
throw new Error('Useful message');
} catch (error) {
console.log('Something went wrong! ' + error.message);
}
Operationsordning plus avancerade tankar
Utan ett testfångstblock kommer odefinierade funktioner att kasta fel och stoppa körningen:
undefinedFunction("This will not get executed");
console.log("I will never run because of the uncaught error!");
Kasta ett fel och inte köra den andra raden:
// Uncaught ReferenceError: undefinedFunction is not defined
Du behöver ett testfångstblock, liknande andra språk, för att säkerställa att du fångar det felet så att koden kan fortsätta att köra:
try {
undefinedFunction("This will not get executed");
} catch(error) {
console.log("An error occured!", error);
} finally {
console.log("The code-block has finished");
}
console.log("I will run because we caught the error!");
Nu har vi tagit emot felet och kan vara säker på att vår kod kommer att köras
// An error occured! ReferenceError: undefinedFunction is not defined(…)
// The code-block has finished
// I will run because we caught the error!
Vad händer om ett fel inträffar i vårt fångstblock !?
try {
undefinedFunction("This will not get executed");
} catch(error) {
otherUndefinedFunction("Uh oh... ");
console.log("An error occured!", error);
} finally {
console.log("The code-block has finished");
}
console.log("I won't run because of the uncaught error in the catch block!");
Vi kommer inte att bearbeta resten av vårt fångstblock, och exekveringen kommer att stanna förutom det slutliga blocket.
// The code-block has finished
// Uncaught ReferenceError: otherUndefinedFunction is not defined(…)
Du kan alltid häcka dina försök att fånga block ... men du borde inte för det kommer att bli extremt rörigt ..
try {
undefinedFunction("This will not get executed");
} catch(error) {
try {
otherUndefinedFunction("Uh oh... ");
} catch(error2) {
console.log("Too much nesting is bad for my heart and soul...");
}
console.log("An error occured!", error);
} finally {
console.log("The code-block has finished");
}
console.log("I will run because we caught the error!");
Fångar upp alla fel från föregående exempel och loggar följande:
//Too much nesting is bad for my heart and soul...
//An error occured! ReferenceError: undefinedFunction is not defined(…)
//The code-block has finished
//I will run because we caught the error!
Så hur kan vi fånga alla fel !? För odefinierade variabler och funktioner: du kan inte.
Du bör inte heller linda in alla variabler och funktioner i ett try / catch-block, eftersom det här är enkla exempel som bara kommer att inträffa en gång tills du fixar dem. För objekt, funktioner och andra variabler som du vet finns men du inte vet om deras egenskaper eller delprocesser eller biverkningar kommer att existera, eller om du förväntar dig några feltillstånd under vissa omständigheter bör du abstrahera din felhantering på något sätt. Här är ett mycket grundläggande exempel och implementering.
Utan ett skyddat sätt att kalla pålitliga eller undantagskastmetoder:
function foo(a, b, c) {
console.log(a, b, c);
throw new Error("custom error!");
}
try {
foo(1, 2, 3);
} catch(e) {
try {
foo(4, 5, 6);
} catch(e2) {
console.log("We had to nest because there's currently no other way...");
}
console.log(e);
}
// 1 2 3
// 4 5 6
// We had to nest because there's currently no other way...
// Error: custom error!(…)
Och med skydd:
function foo(a, b, c) {
console.log(a, b, c);
throw new Error("custom error!");
}
function protectedFunction(fn, ...args) {
try {
fn.apply(this, args);
} catch (e) {
console.log("caught error: " + e.name + " -> " + e.message);
}
}
protectedFunction(foo, 1, 2, 3);
protectedFunction(foo, 4, 5, 6);
// 1 2 3
// caught error: Error -> custom error!
// 4 5 6
// caught error: Error -> custom error!
Vi fångar fel och behandlar fortfarande alla förväntade koder, dock med en något annan syntax. Hur som helst fungerar, men när du bygger mer avancerade applikationer kommer du att vilja börja fundera över sätt att abstrahera din felhantering.
Feltyper
Det finns sex specifika kärnfelskonstruktörer i JavaScript:
EvalError
- skapar en instans som representerar ett fel som uppstår när det gäller den globala funktionsevalueringeneval()
.InternalError
- skapar en instans som representerar ett fel som uppstår när ett internt fel i JavaScript-motorn kastas. Till exempel "för mycket rekursion". (Stöds endast av Mozilla Firefox )RangeError
- skapar en instans som representerar ett fel som uppstår när en numerisk variabel eller parameter ligger utanför dess giltiga intervall.ReferenceError
- skapar en instans som representerar ett fel som inträffar när du avgränsar en ogiltig referens.SyntaxError
- skapar en instans som representerar ett syntaxfel som inträffar när du analyserar koden ieval()
.TypeError
- skapar en instans som representerar ett fel som uppstår när en variabel eller parameter inte är av en giltig typ.URIError
- skapar en instans som representerar ett fel som uppstår närencodeURI()
ellerdecodeURI()
skickas ogiltiga parametrar.
Om du implementerar felhanteringsmekanismen kan du kontrollera vilken typ av fel du får från koden.
try {
throw new TypeError();
}
catch (e){
if(e instanceof Error){
console.log('instance of general Error constructor');
}
if(e instanceof TypeError) {
console.log('type error');
}
}
I sådant fall kommer e
att vara ett exempel på TypeError
. Alla feltyper utökar baskonstruktorn Error
, därför är det också ett exempel på Error
.
Att ha detta i åtanke visar oss att det är värdelöst att kontrollera e
att vara en förekomst av Error
i de flesta fall.