JavaScript try...catch...finally 语句

在介绍 JavaScript try...catch...finally 语句之前,我们先来看一个简单的例子。

示例 1:没有使用 try...catch

function add(a, b) {
    return a + b;
}

// 第 1 次计算
const num1 = 50;
const num2 = JSON.parse("abc");
console.log(add(num1, num2));

// 第 2 次计算
console.log(add(10, 20));

运行结果如下。

(报错)SyntaxError: Unexpected token 'a', "abc" is not valid JSON

分析:

在这个例子中,我们首先定义了一个名为 “add” 的函数,用于计算两个数的和。然后尝试调用 2 次 add() 来进行计算。但是在第 1 次计算的时候,由于 JSON.parse() 解析会报错,然后导致后面所有的程序都执行不了了,包括第 2 次计算。

如果希望在第 1 次计算的时候,即使报错也不会影响后面的程序(比如第 2 次计算),此时应该怎么办呢?这个时候就可以使用 try...catch 语句来解决这个问题。

JavaScript try...catch 语句

在 JavaScript 中,我们可以使用 try...catch 语句来测试一段可能出错的代码,并且在出错的时候捕获到这个错误,从而防止程序崩溃,影响后面程序的执行。

语法:

try {
    // 可能出错的代码
} catch (error) {
    // 出错时如何处理
}

分析:

对于 try...catch 语句来说,它主要由 2 部分组成:

  • try 块:用于包含可能出错的代码。
  • catch 块:它接收一个参数(通常命名为 error),代表抛出的异常对象。

也就是说,如果 “try 块” 报错了,就会去执行 “catch 块” 代码,并且也不会影响后面程序的执行。

示例 2:使用 try...catch 处理

function add(a, b) {
    return a + b;
}

try {
    // 第 1 组
    const num1 = 50;
    const num2 = JSON.parse("abc");
    console.log(add(num1, num2));
} catch (error) {
    console.log(error.name);
    console.log(error.message);
}

// 第 2 组
console.log(add(10, 20));

运行结果如下。

SyntaxError
Unexpected token 'a', "abc" is not valid JSON
30

分析:

对于这个例子中,try 块执行到 const num2 = JSON.parse("abc"); 这一句代码时,会抛出 SyntaxError 异常。需要注意的是,此时 JavaScript 会立即停止执行 try 块中 “剩余的代码”,并跳转到 catch 块中。

当 catch 块中的代码执行完成之后,JavaScript 会继续执行 try...catch 之后的代码,从而避免异常代码导致整个程序崩溃。

error 是一个错误对象(也叫 “异常对象”),它主要包含 2 个属性:

  • name:错误的类型名称,比如:SyntaxError、TypeError、ReferenceError 等。
  • message:错误的详细信息。

JavaScript try...catch...finally 语句

在处理 JavaScript 异常时,如果希望 try 代码块不管有没有发生异常,都继续执行某些语句,我们可以使用 finally 子句来实现。

语法:

try {
    // 可能出错的代码
} catch (error) {
    // 出错时如何处理
} finally {
    // 无论是否发生异常,这部分代码都会执行
}

说明:

finally 子句一般用于执行清理工作,比如关闭文件连接、释放资源、重置变量等。

示例 3:try...catch...finally 基本用法

async function fetchUserData() {
    let isLoading = true;    // 开始动画
    console.log("正在加载...");

    try {
        // 假设这里是一个接口请求,这里用 Promise 模拟
        let response = await fakeFetch(); 
        console.log("用户数据:", response);
    } catch (error) {
        console.log("获取失败:", error.message);
    } finally {
        isLoading = false;    // 不管成功失败,都停止动画
        console.log("加载结束");
    }
}

// 模拟网络请求函数
function fakeFetch() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve({ id: 1, name: "张三" });
        }, 1000);
    });
}

fetchUserData();

运行结果如下。

正在加载...
用户数据: {"id":1,"name":"张三"}
加载结束

分析:

try...catch...finally 最常见的场景之一,就是用于处理 AJAX 请求中的动画。就拿咱们绿叶网的 “Java 在线编译器” 来说,当点击【运行代码】按钮之后,会设置动画的开始(let isLoading = true;),然后就会向服务器发起一个请求。然后我们希望不管这个请求是成功还是失败,都要停止动画(isLoading = false;)。此时就需要使用 finally 子句来实现。

这个使用场景非常经典,也非常有用,小伙伴们要多加斟酌理解一下。

JavaScript try...catch...finally 应用场景

在 JavaScript 中,try...catch...finally 语句主要使用场景,就是可以使得我们的程序在遇到错误时能够优雅地失败,而不是完全崩溃。它的主要应用场景包括:

1. 处理不确定的数据(比如用户输入)

表单中用户的输入数据,从网络或文件拿到的数据(比如 JSON 格式),可能会出现格式不规范等问题,此时会导致程序直接崩溃。

像这样可能出错的数据,最好的办法是使用 try...catch 语句来处理。如果失败了(比如不是一个有效的 JSON 格式),程序就不会崩溃,而是会执行 catch 里面的代码,友好地提示用户。

try {
    // 尝试把用户的输入当成 JSON 来解析
    let data = JSON.parse(userInput);
} catch (error) {
    // 如果解析失败了,就执行这里面的代码
    console.log("输入格式不正确");
}

2. 处理 AJAX 请求

从网络上获取数据(比如发送 AJAX 或 Fetch 请求)时,可能会遇到各种网络问题,例如断网、服务器宕机、请求超时等等,这些都可能导致程序出错。

我们可以尝试在 “try 块” 中发送请求并等待结果,如果网络连接或请求本身发生错误(而不是服务器返回的错误状态码,而是网络连接上的错误),就在 “catch 块” 中捕获它,然后给用户一个友好的提示。

try {
    // 尝试连接并获取数据
    const res = await fetch("https://api.example.com/user");
} catch (error) {
    // 如果网络连接失败了,就执行这里面的代码
    console.log("网络连接失败,请检查网络后重试。");
}

3. 处理本地存储(localStorage)

如果我们想在浏览器里本地存储一些数据 (localStorage),但在一些特殊情况下,比如用户禁用了存储功能,或者存储空间满了,此时尝试存储或读取数据会抛出错误。

我们可以在 “try 块” 中尝试去读取或写入本地存储,如果这个操作因为权限或空间问题而失败,此时 “catch 块” 就会捕获到错误,防止程序卡住,并可以告诉用户发生了什么。

try {
    // 尝试从本地存储中获取数据
    let data = localStorage.getItem("data");
} catch (error) {
    // 如果因为某些限制导致操作失败,就执行这里面的代码
    console.log("获取数据失败,可能是你禁用了存储功能。");
}

总而言之一句话,就是:try...catch...finally 语句适用于那些 “可能失败但不希望影响整个程序” 的代码

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号