头图

再见 Try/Catch,在 TypeScript 中更优雅地处理错误

原文链接:No more Try/Catch: a better way to handle errors in TypeScript
作者:Noah
译者:倔强青铜三

前言

大家好,我是倔强青铜三。是一名热情的软件工程师,我热衷于分享和传播IT技术,致力于通过我的知识和技能推动技术交流与创新,欢迎关注我,微信公众号:倔强青铜三。欢迎点赞、收藏、关注,一键三连!!!

用“错误捕获”替代 Try/Catch:TypeScript 错误处理新思路

在开发 TypeScript 应用程序时,你是否觉得传统的 Try/Catch 错误处理方式有些繁琐?最近,我在 YouTube 上看到一个有趣的视频,介绍了一种更简洁的错误处理方法。今天,我将分享视频中的核心内容,并结合自己的理解进行总结。

定义 getUser 函数用于错误处理

首先,我们定义一个简单的 getUser 函数来演示错误处理。该函数根据给定的 id 返回一个用户对象。

TypeScript复制

const wait = (duration: number) => {
  return new Promise((resolve) => {
    setTimeout(resolve, duration);
  });
};

const getUser = async (id: number) => {
  await wait(1000);

  if (id === 2) {
    throw new Error("404 - User does not exist");
  }

  return { id, name: "Noah" };
};

const user = await getUser(1);

console.log(user); // { id: 1, name: "Noah" }

使用 try/catch 进行错误处理

将上述代码改写为使用 try/catch 的形式,代码如下:

TypeScript复制

const wait = (duration: number) => {
  ...
};

const getUser = async (id: number) => {
  ...
};

try {
  const user = await getUser(1);
  console.log(user); // { id: 1, name: "Noah" }
} catch (error) {
  console.log("There was an error");
}

try/catch 的问题 ①:捕获了 try 块内的所有错误

以下代码存在问题。即使只是一个拼写错误,控制台也会显示“There was an error”,而我只想捕获 getUser 中发生的错误。

TypeScript复制

const wait = (duration: number) => {
  ...
};

const getUser = async (id: number) => {
  ...
};

try {
  const user = await getUser(1);
  console.log(usr); // ← 拼写错误
  // ... (大量代码)
} catch (error) {
  console.log("There was an error");
}

try/catch 的问题 ②:使用 let 的陷阱

尝试使用 let 解决问题,代码如下:

TypeScript复制

const wait = (duration: number) => {
  ...
};

const getUser = async (id: number) => {
  ...
};

let user;

try {
  user = await getUser(1);
  // ... (大量代码)
} catch (error) {
  console.log("There was an error");
}

console.log(usr); // ← ReferenceError: Can't find variable: usr

虽然拼写错误引发了实际错误,但这段代码仍不理想,因为可能会意外重新定义 user 对象,例如:

TypeScript复制

const wait = (duration: number) => {
  ...
};

const getUser = async (id: number) => {
  ...
};

let user;

try {
  user = await getUser(1);
  // ... (大量代码)
} catch (error) {
  console.log("There was an error");
}

user = 1; // ← ❌ 可能引发错误

解决方案

使用 catchError 函数可以更简洁、更易读地处理错误。此外,user 变量是不可变的,不会引发意外错误。

TypeScript复制

const wait = (duration: number) => {
  ...
};

const getUser = async (id: number) => {
  ...
};

const catchError = async <T>(promise: Promise<T>): Promise<[undefined, T] | [Error]> => {
  return promise
    .then((data) => {
      return [undefined, data] as [undefined, T];
    })
    .catch((error) => {
      return [error];
    });
};

const [error, user] = await catchError(getUser(1));

if (error) {
  console.log(error);
}

console.log(user);

如果你对这种模式是否实用有疑问,可以参考视频中的详细解释。我虽然没有在实际工作中使用过这种模式,但很想知道大家的看法。因为视频评论区中也讨论过这个问题,我希望能从大家的反馈中探索最佳实践。祝大家编码愉快☀️

最后感谢阅读!欢迎关注我,微信公众号倔强青铜三。欢迎点赞收藏关注,一键三连!!!

倔强青铜三
36 声望0 粉丝