Javascript 简明教程

JavaScript - try…​catch

JavaScript try…​catch Statement

JavaScript 中的 try-catch statement 用于处理运行时错误(异常)。这在大多数编程语言中非常常见,用于处理异常。try-catch 语句只能处理运行时错误。try 块后面必须紧跟一个 catch 块或一个 finally 块(或两者之一)。

The try-catch statement in JavaScript is used to handle the runtime errors (exceptions). This is very common in most programming languages to handle exceptions. A try-catch statement can handle only runtime errors. The try block must be followed by either exactly one catch block or one finally block (or one of both).

try{} statement 内部,你可以编写带有错误或可能出现错误的代码。你可以在 try{} 语句中添加常规 JavaScript 代码。

Inside the try{} statement, you can write the code having errors or possibilities of the errors. You can add regular JavaScript code into the try{} statement.

catch{} statement 用于处理错误。当 try{} 语句的代码中出现任何错误时,JavaScript 运行引擎将执行 catch{} 语句的代码来处理错误。

The catch{} statement is used to handle the errors. When any error occurs in the code of the try{} statement, the JavaScript run engine executes the code of the catch{} statement to handle the errors.

如果 try{} 语句的代码中没有错误,它将跳过 catch{} 语句的代码并执行代码的下一行。

If no error occurs in the code of the try{} statement, it will skip the code of the catch{} statement and execute the next lines of the code.

Syntax

你可以按照下面的语法在代码中使用 try-catch 语句来处理异常。

You can follow the syntax below to use the try-catch statements in the code to handle exceptions.

try {
   // JavaScript code
} catch(error) {
   // Handle error
}

你可以在 catch{} 语句中打印错误对象或基于错误类型自定义错误消息以显示错误。

You can print the error object in the catch{} statement or the custom error message based on the error type to show errors.

Parameters

  1. error − The catch{} statement takes the ‘error’ object as a parameter. It contains the name and message property. However, it is an optional parameter.

Example

在下面的代码中,我们在 try{} 语句内部将“num1”变量的值赋给“num”变量。这里,“num1”变量没有定义。因此,它将抛出一个错误。

In the code below, we assign the ‘num1’ variable’s value to the ‘num’ variable inside the try{} statement. Here, the ‘num1’ variable is not defined. So, it will throw an error.

在 catch{} 语句中,我们打印错误对象的“name”和“message”属性的值。

In the catch{} statement, we print the value of the error object’s ‘name’ and ‘message’ property.

在输出中,你可以看到它抛出一个引用错误并带有适当的错误消息。

In the output, you can observe that it throws a reference error with a proper error message.

<html>
<body>
   <div id = "demo"> </div>
   <script>
      const output = document.getElementById("demo");
      try {
         let num = num1;
      } catch (err) {
         output.innerHTML += "The error name is: " + err.name + "<br>";
         output.innerHTML += "The error message is: " + err.message + ".<br>";
      }
   </script>
</body>
</html>

Output

The error name is: ReferenceError
The error message is: num1 is not defined.

当 try{} 语句中出现任何错误时,它将跳过剩余代码的执行并执行 catch{} 语句的代码。

When any error occurs in the try{} statement, it skips the execution of the remaining code and executes the code of the catch{} statement.

让我们通过以下示例了解它。

Let’s understand it via the example below.

Example

在下面的代码中,我们调用 welcome() 函数,它没有被定义。因此,它将抛出一个引用错误。

In the code below, we invoke the welcome() function, which is not defined. So, it will throw a reference error.

在 catch{} 语句中,我们处理错误。

In the catch{} statement, we handle the error.

在输出中,你可以看到它打印 try{} 语句的开始消息、catch{} 语句的开始消息以及错误消息。它跳过 try{} 语句的结束消息,因为在该消息之前出现了一个错误。

In the output, you can see that it prints the start message of the try{} statement, the start message of the catch{} statement, and the error message. It skips the end message of the try{} statement as an error occurs before that.

<html>
<body>
   <div id = "demo"> </div>
   <script>
      const output = document.getElementById("demo");
      try {
         output.innerHTML += "In the start of try block <br>";
         welcome();
         output.innerHTML += "In the end of try block <br>";
      } catch (err) {
         output.innerHTML += "In the catch block <br>";
         output.innerHTML += "The error name is: " + err.name + "<br>";
         output.innerHTML += "The error message is: " + err.message + ".<br>";
      }
   </script>
</body>
</html>

Output

In the start of try block
In the catch block
The error name is: ReferenceError
The error message is: welcomeis not defined.

Note − try-catch 语句不允许你处理语法错误。它只能处理运行时错误。

Note − The try-catch statement doesn’t allow you to handle the syntax errors. It can handle only runtime errors.

例如,如果您运行以下代码。它将在浏览器的控制台中显示一个错误,但无法使用 {} 语句捕获该错误。

For example, if you run the below code. It will show you an error in the browser’s console but can’t catch the error using the {} statement.

try {
   let num = ;
} catch (err) {
   // Error handling
}

JavaScript try…catch…finally Statement

finally{} 语句允许你在执行 try{} 和 catch{} 语句后执行特定代码。

The finally{} statement allows you to execute the particular code after completing the execution of the try{} and catch{} statements.

无论错误是否发生在 try{} 语句的代码中,JavaScript 总是执行 finally{} 语句的代码。如果发生错误,它将执行 catch{} 语句的代码,然后执行 finally{} 语句的代码。

JavaScript always executes the code of the finally{} statement, whether the error occurs in the code of the try{} statement. If an error occurs, it executes the code of the catch{} statement and then executes the code of the finally{} statement.

Example

在下面的代码中,我们将变量 'b' 的值分配给 try{} 语句中的变量 'a'。它会引发错误。

In the code below, we assign the value of the variable 'b' to the variable 'a' inside the try{} statement. It throws an error.

在 catch{} 语句中,我们打印错误。

In the catch{} statement, we print the error.

在 finally{} 语句中,它打印消息。

In the finally{} statement, it prints the message.

你可以观察到输出首先运行 try{} 语句的代码,接下来运行 catch{} 语句的代码,最后运行 finally{} 语句的代码。

You can observe the output that it runs the code of the try{} statement first, the code of the catch{} statement after that, and the code of the finally{} statement at last.

<html>
<body>
   <div id = "output"> </div>
   <script>
      try {
         let a = b;
      } catch (e) {
         document.getElementById("output").innerHTML = e;
      }
      finally {
         document.getElementById("output").innerHTML += "<br>Finally block always executes";
      }
   </script>
</body>
</html>

Output

ReferenceError: b is not defined
Finally block always executes

Example

在下面的示例中,我们将没有错误的代码写入 try{} 语句。

In the example below, we have written the code without any error into the try{} statement.

我们还添加了 catch{} 和 finally{} 语句。

Also, we have added the catch{} and finally{} statements.

输出显示它执行 try{} 语句代码,然后执行 finally{} 语句代码。它跳过执行 catch{} 语句,因为代码没有错误。

The output shows that it executes the try{} statement code and finally{} statement code after that. It skips the execution of the catch{} statement, as the code is error-free.

<html>
<body>
   <div id = "demo"> </div>
   <script>
      const output = document.getElementById("demo");
      try {
         let a = 10;
         output.innerHTML = "Value of a is " + a + "<br>";
      } catch (e) {
         output.innerHTML = e.name + " : " + e.message;
      }
      finally {
         output.innerHTML += "Inside the finally block.";
      }
   </script>
</body>
</html>

Output

Value of a is 10
Inside the finally block.

JavaScript Throw Statement

当代码中发生任何错误时,JavaScript 会默认抛出一个错误。但你也可以手动抛出错误。例如,你正在进行表单数据验证。如果数据无效,你可以抛出错误并要求用户更正数据。

When any error occurs in the code, JavaScript throws an error by default. But you can also throw the error manually. For example, you are doing the form data validation. If the data is invalid, you can throw the error and ask users to correct the data.

当你使用“throw”语句抛出错误时,try{} 语句中随后出现的代码将不会执行,并且它将执行 catch{} 语句的代码。

When you throw an error using the ‘throw’ statement, the code present after that in the try{} statement will not executed, and it will execute the code of the catch{} statement.

你可以按照下面的语法使用“throw”语句抛出错误。

You can follow the syntax below to throw an error using the ‘throw’ statement.

throw <error>;

在上面的语法中,<error> 可以是“错误”对象、字符串、数字、基本值或特定类型的错误对象。一个好的做法是抛出一个错误对象,而不是抛出一个基本值。

In the above syntax, <error> can be a ‘Error’ object, string, number, primitive value, or a particular type of error object. It is a good practice to throw an Error object rather than throwing the primitive value.

Example: Throwing the Error object

在下面的代码中,我们使用“throw”语句从 try{} 语句中抛出一个错误对象。它停止执行“throw”语句的剩余代码,并执行 catch{} 语句的代码。

In the code below, we throw an Error object from the try{} statement using the ‘throw’ statement. It stops the execution of the remaining code of the ‘throw’ statement and executes the code of the catch{} statement.

<html>
<body>
   <div id = "demo"> </div>
   <script>
      const output = document.getElementById("demo");
      try {
         output.innerHTML += "Start of the try block. <br />";
         throw new Error("Custom error");
         output.innerHTML += "End of the try block. <br />"; //not executed
      } catch (e) {
         output.innerHTML += "Catch block: Caught exception. <br />";
         output.innerHTML += e.name + " : " + e.message;
      }
   </script>
</body>
</html>

Output

Start of the try block
Catch block: Caught exception.
Error: Custom error

Example: Throwing the primitive value

在下面的代码中,我们从 try{} 语句中抛出原始数字值。在 catch{} 语句中,我们获取抛出的原始值并将其打印出来。

In the code below, we throw the primitive numeric value from the try{} statement. In the catch{} statement, we get the thrown primitive value and print it.

<html>
<body>
   <div id = "output">The error message is:  </div>
   <script>
      try {
         throw 20;
      } catch (e) {
         document.getElementById("output").innerHTML += e;
      }
   </script>
</body>
</html>

Output

The error message is: 20

Example: Input Validation Example

在下面的代码中,我们定义了数字类型的 <input> 元素,以获取用户的年龄作为输入。

In the code below, we have defined the <input> element of the number type to take the user age as an input.

当用户单击提交年龄按钮时,它会调用 handleAge() 函数。handleAge() 函数检查年龄是否小于 18 岁。如果是,它会抛出 RangeError。

When the user clicks the submit age button, it invokes the handleAge() function. The handleAge() function checks whether the age is less than 18. If yes, it throws the rangeError.

catch{} 语句打印错误消息以验证年龄。

The catch{} statement prints the error message to validate the age.

<html>
<body>
   <p>Age: <input type = "number" id = "age" value = "20"></p>
   <button onclick = "handleAge()"> Submit Age </button>
   <p id = "demo"> </p>
   <script>
      const output = document.getElementById("demo");
      function handleAge() {
         let age = document.getElementById("age").value;
         try {
            if (age < 18) {
               throw RangeError("You are not eligible to vote");
            } else {
               output.innerHTML += "<br>You are eligible to vote";
            }
         } catch (e) {
            output.innerHTML += "<br>The error is - " + e;
         }
      }
   </script>
</body>
</html>

Output

Age: 20
Submit Age
The error is - RangeError: You are not eligible to vote

Nesting Try Blocks

有时,需要开发人员编写嵌套的 try-catch 语句。嵌套的 try-catch 表示 try 块位于 try 块内。

Sometimes, developers are required to write the nested try-catch statements. The nested try-catch means a try block inside the try block.

如果内部 catch{} 语句无法处理错误,则外部 catch{} 语句可以处理该错误。你也可以跳过内部 catch{} 语句,但这种情况下,需使用 finally{} 语句编写 try{} 语句。

If the inner catch{} statement can’t handle the error, the outer catch{} statement may handle it. You can also skip the inner catch{} statement, but in this case, you need to write the finally{} statement with the try{} statement.

Example

在下面的代码中,使用两个嵌套的 try{} 语句。我们已将 try-finally 语句添加到外部 try{} 语句中。

We have used the two nested try{} statements in the code below. We have added the try-finally statement inside the outer try{} statement.

内部 try{} 语句抛出错误,由外部 catch{} 语句处理。

The inner try{} statement throws the error, handled in the outer catch{} statement.

<html>
<body>
   <div id = "demo"> </div>
   <script>
      const output = document.getElementById("demo");
      try {
         try {
            throw Error("Error in the inner try block");
         } finally {
            output.innerHTML += "Inside the inner finally block. <br>";
         }
      } catch (e) {
         output.innerHTML += "Inside the outer catch block. <br>";
         output.innerHTML += "Error: " + e.message;
      }
   </script>
</body>
</html>

Output

Inside the inner finally block.
Inside the outer catch block.
Error: Error in the inner try block

The Rethrow Error

有时,catch{} 语句可能无法处理错误。在这种情况下,可以使用“throw”语句从 catch 块中重新抛出错误。

Sometimes, it can happen that the catch{} statement can’t handle the error. In such cases, you can rethrow the error from the catch block using the ‘throw’ statement.

如果可用,外部 catch{} 语句可以处理重新抛出的错误。

The outer catch{} statement can handle the rethrown error if it is available.

Example

在下面的代码中,我们创建了两个嵌套的 try-catch 块。在内部 try 块中,我们使用“throw”语句抛出错误。内部 catch{} 语句将捕获错误,然后我们从内部 catch{} 语句重新抛出错误。

In the code below, we have created the two nested try-catch blocks. In the inner try block, we throw the error using the ‘throw’ statement. The inner catch{} statement will catch the error, and we rethrow the error from the inner catch{} statement.

然后,我们在外部 catch{} 语句中处理错误。

After that, we handle the error in the outer catch{} statement.

<html>
<body>
   <div id = "demo"> </div>
   <script>
      let output = document.getElementById("demo");
      try {
         try {
            throw 20;
         } catch (e) {
            // Rethrowing the error.
            output.innerHTML = "Inside the inner catch block. <br>";
            output.innerHTML += "Error: " + e + "<br> <br>";
            throw e;
         }
      } catch (e) {
         output.innerHTML += "Inside the outer catch block. <br>";
         output.innerHTML += "Error: " + e;
      }
   </script>
</body>
</html>

Output

inside the inner catch block.
Error: 20

Inside the outer catch block.
Error: 20

Conditional Catch-blocks

在 catch{} 块内,可以使用 if-else 语句有条件地处理错误。这样,可以对多个 try{} 语句使用单个 catch{} 语句。

Inside the catch{} block, you can use the if-else statement to handle the errors conditionally. In this way, you can use the single catch{} statement for the multiple try{} statements.

在 catch{} 语句中,可以使用“instanceOf”运算符检查错误的类型,并根据错误类型处理错误。

In the catch{} statement, you can check the type of the error using the ‘instanceOf’ operator and handle the error according to the error type.

Example

在下面的代码中,我们在 try{} 语句内调用 welcome 函数,并且未定义 welcome() 函数。

In the code below, we have called the welcome function inside the try{} statement, and the welcome() function is not defined.

在 catch{} 语句中,我们使用“instanceOf”运算符检查错误的类型,并根据错误的类型在网页上打印消息。

In the catch{} statement, we check the type of the error using the ‘instanceOf’ operator and print the message on the web page according to the type of the error.

<html>
<body>
   <div id = "demo"> </div>
   <script>
      const output = document.getElementById("demo");
      try {
         welcome(); // Function not defined
      } catch (e) {
         if (e instanceof ReferenceError) {
            output.innerHTML = "Reference error is occurred.";
         } else if (e instanceof TypeError) {
            output.innerHTML = "Type error is occurred.";
         } else if (e instanceof RangeError) {
            output.innerHTML = "Range error is occurred.";
         } else if (e instanceof SyntaxError) {
            output.innerHTML = "Syntax error is occurred.";
         } else {
            output.innerHTML = "Error is occurred.";
         }
      }
   </script>
</body>
</html>

Output

Reference error is occurred.

JavaScript try…​catch with setTimeout() Method

对异步 JavaScript 代码使用 try-catch 语句不会捕获从 try 块抛出的错误。

Using the try-catch statement with the asynchronous JavaScript code won’t catch the error thrown from the try block.

原因是,当所有主线程代码执行完成后,JavaScript 才会执行异步代码。

The reason is that JavaScript executes the asynchronous code, when all main thread code gets executed.

让我们通过以下示例了解它。

Let’s understand it via the example below.

Example

在下面的代码中,我们在 try{} 语句内使用了 setTimeOut() 方法。它在 1000 毫秒后执行回调函数。在回调函数中,我们使用“throw”语句抛出错误。

In the code below, we used the setTimeOut() method inside the try{} statement. It executes the callback function after 1000 milliseconds. In the callback function, we throw the error using the ‘throw’ statement.

在输出中,你可以看到 catch{} 语句没有捕获错误,并在浏览器的控制台中打印错误。

In the output, you can observe that the cathc{} statement is not catching the error, and it prints the error in the browser’s console.

<html>
<body>
   <div id = "demo"> </div>
   <script>
      const output = document.getElementById("demo");
      try {
         output.innerHTML = "Inside the try block. <br>";
         setTimeout(() => {
            throw new Error("Whoops!");
         }, 1000);
      } catch (err) {
         output.innerHTML += "Inside the catch block. <br>";
         output.innerHTML = err;
      }
   </script>
</body>
</html>

Output

Inside the try block.

Promise-based Errors

如果在使用 Promise 代码时发生任何错误,可以使用 catch() 方法处理错误。或者,可以将错误处理程序作为 then() 方法的第二个参数传递。

When any error occurs while consuming the promise code, you can use the catch() method to handle the error. Alternatively, you can pass the error handler as a second parameter of the then() method.

Examples

在下面的代码中,我们创建了 Promise 并在一千毫秒后将其拒绝。

In the code below, we have created the promise and rejected it after 1000 milliseconds.

然后,我们使用 then() 和 catch() 方法处理 Promise。此处,我们拒绝 Promise,以便控件执行 catch() 方法的代码。

After that, we used the then() and catch() method to handle the promise. Here, we have rejected the promise so that control will execute the code of the catch() method.

<html>
<body>
   <div id = "demo"> </div>
   <script>
      const output = document.getElementById("demo");
      output.innerHTML = "The promise is pending...";
      let promise = new Promise((resolve, reject) => {
         setTimeout(() => {
            reject("The promise is rejected!");
         }, 1000);
      });
      promise
      .then((result) => {
         output.innerHTML = result;
      })
      .catch((error) => {
         output.innerHTML = error;
      });
   </script>
</body>
</html>

Output

The promise is rejected !

Types of Errors in JavaScript

JavaScript 中有不同类型的错误。在这里,我们将学习每种类型的错误和示例。

There are different types of errors that JavaScript can throw. Here, we will learn each type one by one with examples.

JavaScript Range Error

当值超出指定范围时,JavaScript 代码会抛出范围错误。

The JavaScript code throws a range error when the value is out of the specified range.

在下面的代码中,我们使用了 toPrecision() 方法并传递 1000 作为参数。它抛出范围错误,因为数字不能有 1000 个位数。

In the code below, we used the toPrecision() method and passed 1000 as an argument. It throws the range error, as the number can’t have 1000 digits.

<html>
<body>
   <div id = "output"> </div>
   <script>
      try {
         let num = 10;
         num.toPrecision(1000);
      } catch (err) {
         document.getElementById("output").innerHTML = err;
      }
   </script>
</body>
</html>
RangeError: toPrecision() argument must be between 1 and 100

JavaScript Reference Error

当尝试访问未定义的变量、函数、类方法等时,会发生引用错误。

The reference error occurs when you try to access the undefined variables, functions, class methods, etc.

在下面的代码中,我们执行了“window”对象的 test() 方法。这里未定义 test() 方法,因此会抛出引用错误。

In the code below, we execute the test() method of the ‘window’ object. Here, the test() method is not defined, so it throws the reference error.

<html>
<body>
   <div id = "output"> </div>
   <script>
      try {
         window.test();
      } catch (err) {
         document.getElementById("output").innerHTML = err;
      }
   </script>
</body>
</html>
TypeError: window.test is not a function

JavaScript Type Error

如果你在方法或操作符中未使用有效类型的变量,JavaScript 代码会抛出类型错误。

The JavaScript code throws the type error if you don’t use the values of the valid type with methods or operators.

在下面的示例中,我们对布尔变量使用了 toLowerCase() 方法,但 toLowerCase() 方法仅受字符串值支持。因此,它抛出类型错误。

In the example below, we use the toLowerCase() method with the boolean variable, but the toLowerCase() method is supported by string values only. So, it throws the type error.

<html>
<body>
   <div id = "output"> </div>
   <script>
      try {
         let bool = true;
         bool.toLowerCase();
      } catch (err) {
         document.getElementById("output").innerHTML = err;
      }
   </script>
</body>
</html>
TypeError: bool.toLowerCase is not a function

JavaScript URI (Uniform Resource Identifier) Error

当未将有效 URL 作为 encodeURI、decodeURI 等方法的参数传递时,会发生 URI 错误。

The URI error occurs when you don’t pass the valid URL as an argument of the encodeURI, decodeURI, etc. methods.

在下面的示例中,我们将无效的编码 URI 作为 decodeURI() 方法的参数传递。因此,它抛出 URIError。

In the example below, we passed the invalid encoded URI as an argument of the decodeURI() method. So, it throws the URIError.

<html>
<body>
   <div id = "output"> </div>
   <script>
      try {
         decodeURI("%");
      } catch (err) {
         document.getElementById("output").innerHTML = err;
      }
   </script>
</body>
</html>

Output

URIError: URI malformed