什么是异常
Error objects are thrown when runtime errors occur. The Error object can also be used as a base object for user-defined exceptions. 
描述的很简单,我们总结一下就是代码在执行过程中遇到了问题,程序已经无法正常运行了,Error对象会被抛出,这一点它不同于大部分编程语言里使用的异常对象Exception,甚至更适合称之为错误,应该说事实也确实如此,Error对象在未被抛出时候和js里其他的普通对象没有任何差别是不会引发异常的,同时Error 对象也可用于用户自定义错误的基础对象。
  
  
    
   
   
     
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
   
   
     
try {  const 123variable = 2;} catch(e) {  console.log('捕获到了:', e)}
  
  
     
  
  
    
   
   
     
  
  
      
     
  
    
   
   
     
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
   
   
     
<script>  function throwSomeError() {    throw new Error('抛个异常玩玩');    console.log('我估计是凉了,不会执行我了!');  }
  throwSomeError();  console.log('那么我呢?')</script>
<script>  console.log('大家猜猜我会执行吗?');</script>
  
  
     
  
  
    
   
   
     
  
  
      
   异常的类型
|  |  |  | 
|  |  |  | 
|  |  |  | 
|  |  |  | 
|  |  |  | 
|  |  |  | 
|  |  |  | 
// 获取分页数据const getPagedData = (pageIndex, pageSize) => {if(pageIndex < 0 || pageSize < 0 || pageSize > 1000) {throw new RangeError(`pageIndex 必须大于0, pageSize必须在0和1000之间`);}return [];}// 转换时间格式const dateFormat = (dateObj) => {if(dateObj instanceof Date) {return 'formated date string';}throw new TypeError('传入的日期类型错误');}
  
  
    
   
   
     
    
    
      
    
    
      
   
   
     
new Error('出错了!');console.log('我吃嘛嘛香,喝嘛嘛棒!'); // 正常输出 '我吃嘛嘛香,喝嘛嘛棒!'
  
  
     
  
  
    
   
   
     
  
  
      
     
  
    
   
   
     
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
   
   
     
// badthrow '出错了';throw 123;throw [];throw null;
  
  
     
  
  
    
   
   
     
  
  
      
   
异常捕获
  
  
    
   
   
     
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
   
   
     
try {  // 要运行的代码,可能引发异常  doSomethingMightThrowError();} catch (error) {  // 处理异常的代码块,当发生异常时将会被捕获,如果不继续throw则不会再向上传播  // error为捕获的异常对象  // 这里一般能让程序恢复的代码  doRecovery();}finally {  // 无论是否出现异常,始终都会执行的代码  doFinally();}
  
  
     
  
  
    
   
   
     
  
  
      
     
  
    
   
   
     
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
   
   
     
// Timeouttry {  setTimeout(() => {    throw Error("定时器出错了!");  }, 1000);} catch (error) {  console.error(error.message);}
// Eventstry {  window.addEventListener("click", function() {    throw Error("点击事件出错了!");  });} catch (error) {  console.error(error.message);}
  
  
     
  
  
    
   
   
     
  
  
      
     
  
    
   
   
     
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
   
   
     
const promiseA = new Promise((resolve,reject)=>{   throw new Error('Promise出错了!');});
const doSomethingWhenResolve = () => {};
const doSomethingWhenReject = (error) => {  logger.log(error)}
// 使用catch捕获const promiseB = promiseA.then(doSomethingWhenResolve).catch(doSomethingWhenReject);// 等价于const promiseB = promise.then(doSomethingWhenResolve, doSomethingWhenResolve);
promiseB.then(() => {  console.log('我又可以正常进到then方法了!');}).catch(()=>{  console.log('不会来这里!');})
  
  
     
  
  
    
   
   
     
  
  
     
  
  
    
   
   
     
  
  
      
   
Prefer Exceptions to Returning Error Codes
1、业务流程更加清晰易读,我们把异常和业务流程理解为两个不同的问题,可以分开去处理;
2、分开来的两个逻辑都更加聚焦,代码更简洁;
  
  
    
   
   
     
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
   
   
     
// Dirtyclass Laptop {  sendShutDown() {    const deviceID = getID(DEVICE_LAPTOP);    if (deviceID !== DEVICE_STATUS.INVALID) {      pauseDevice(deviceID);      clearDeviceWorkQueue(deviceID);      closeDevice(deviceID);    } else {      logger.log('Invalid handle for: ' + DEVICE_LAPTOP.toString());    }  }  getID(status) {    ...    // 总是会返回deviceID,无论是不是合法有效的    return deviceID;  }}// Cleanclass Laptop {  sendShutDown() {    try {      tryToShutDown();    } catch (error) {      logger.log(error);    }  }    tryToShutDown() {    const deviceID = getID(DEVICE_LAPTOP);    pauseDevice(deviceID);    clearDeviceWorkQueue(deviceID);    closeDevice(deviceID);  }
  getID(status) {    ...    throw new DeviceShutDownError('Invalid handle for: ' + deviceID.toString());    ...    return deviceID;  }}
  
  
     
  
  
    
   
   
     
  
  
      
   Don't ignore caught error!
  
  
    
   
   
     
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
   
   
     
// badtry {  doSomethingMightThrowError();} catch (error) {  console.log(error);}
// goodtry {  doSomethingMightThrowError();} catch (error){  console.error(error);  message.error(error.message);  logger.log(error);}
  
  
     
  
  
    
   
   
     
  
  
      
   
Don't ignore rejected promises!
  
  
    
   
   
     
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
   
   
     
// badfetchData().then(doSomethingMightThrowError).catch(console.log);
// goodfetchData() .then(doSomethingMightThrowError) .catch(error => {   console.error(error);   message.error(error.message);   logger.log(error); });
  
  
     
  
  
    
   
   
     
  
  
      
   Exceptions Hierarchy
  
  
    
   
   
     
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
   
   
     
export class RequestException extends Error {  constructor(message) {    super(`RequestException: ${mesage}`);   }}
export class AccountException extends Error {  constructor(message) {    super(`AccountException: ${message}`);  }}
const AccountController = {  getAccount: (id) => {    ...    throw new RequestException('请求账户信息失败!');    ...  }}
// 客户端代码,创建账户const id = 1;const account = AccountController.getAccount(id);if(account){  throw new AccountException('账户已存在!');}
  
  
     
  
  
    
   
   
     
  
  
      
   
Provide context with exceptions
错误边界是一种 React 组件,这种组件可以捕获发生在其子组件树任何位置的 JavaScript 错误,并打印这些错误,同时展示降级 UI,而并不会渲染那些发生崩溃的子组件树。错误边界可以捕获发生在整个子组件树的渲染期间、生命周期方法以及构造函数中的错误。 
  
  
    
   
   
     
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
   
   
     
import { Result } from 'antd';import type { ErrorInfo } from 'react';import React from 'react';
// eslint-disable-next-line @typescript-eslint/ban-typesclass ErrorBoundary extends React.Component<  { children?: React.ReactNode },  { hasError: boolean; errorInfo: string }> {  state = { hasError: false, errorInfo: '' };
  static getDerivedStateFromError(error: Error) {    return { hasError: true, errorInfo: error.message };  }
  componentDidCatch(error: any, errorInfo: ErrorInfo) {    // You can also log the error to an error reporting service    // eslint-disable-next-line no-console    console.log(error, errorInfo);  }
  render() {    if (this.state.hasError) {      // You can render any custom fallback UI      return <Result status="error" title="Something went wrong." extra={this.state.errorInfo} />;    }    return this.props.children;  }}
export { ErrorBoundary };
  
  
     
  
  
    
   
   
     
  
  
      
   window.onerror事件
  
  
    
   
   
     
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
    
    
      
   
   
     
// message:错误信息(字符串)。// source:发生错误的脚本URL(字符串)// lineno:发生错误的行号(数字)// colno:发生错误的列号(数字)// error:Error对象(对象)window.onerror = function(message, source, lineno, colno, error) {   logger.log('捕获到异常:',{ message, source, lineno, colno, error });}
  
  
     
  
  
    
   
   
     
  
  
      
   
unhandledrejection事件
  
  
    
   
   
     
    
    
      
    
    
      
    
    
      
   
   
     
 window.addEventListener('unhandledrejection', (e) => {   console.error('catch', e) }, true)
  
  
     
  
  
    
   
   
     
  
  
      
   1、将面向开发的异常信息转换成更友好的用户界面提示;
参考链接:
[1]https://developer.mozilla.org/zh-CN/Core_JavaScript_1.5_Reference/Global_Functions/eval
[2]https://reactjs.org/docs/error-boundaries.html
往期推荐
《Java工程师必读手册》
工匠追求“术”到极致,其实就是在寻“道”,且离悟“道”也就不远了,亦或是已经得道,这就是“工匠精神”——一种追求“以术得道”的精神。 如果一个工匠只满足于“术”,不能追求“术”到极致去悟“道”,那只是一个靠“术”养家糊口的工匠而已。作者根据多年来的实践探索,总结了大量的Java编码之“术”,试图阐述出心中的Java编码之“道”。
点击阅读原文查看详情。