秋雨
首页
  • HTML
  • CSS
  • JavaScript
设计模式
webpack
  • 前端常识
  • ES
  • React
  • Redux
  • ReactRouter
  • 事件循环
  • 浏览器渲染流程
  • Vue项目性能优化
  • Vue
  • App
Github
首页
  • HTML
  • CSS
  • JavaScript
设计模式
webpack
  • 前端常识
  • ES
  • React
  • Redux
  • ReactRouter
  • 事件循环
  • 浏览器渲染流程
  • Vue项目性能优化
  • Vue
  • App
Github
  • JavaScript基础
  • Object(基础)
  • 数据类型
  • 函数进阶
  • 对象属性配置
  • 原型、继承
  • class
  • 错误处理
  • Promise

错误处理,try...catch

try...catch 语法

try {
  //代码
} catch (err) {
  //错误补货
}

特点:

  • try...catch是同步执行的,异步的错误是不能被捕获的。
try {
  setTimeout(function () {
    noSuchVariable; // 脚本将在这里停止运行
  }, 1000);
} catch (err) {
  alert("不工作");
}

Error 对象

try {
} catch (err) {}

对于所有内建的 error,error 对象具有两个主要属性:

name

Error 名称,例如对于未定义的变量,名称是"ReferenceError"。

message

Error 详细文字描述。

stack

当前的调用栈:用于调试目的的一个字符串,其中包含有关导致 error 的嵌套调用序列的信息。

例如:

try {
  lalala;
} catch (err) {
  alert(err.name); // ReferenceError
  alert(err.message); // lalala is not defined
  alert(err.stack); // ReferenceError: lalala is not defined at (...call stack)

  // 也可以将一个 error 作为整体显示出来
  // error 信息被转换为像 "name: message" 这样的字符串
  alert(err); // ReferenceError: lalala is not defined
}

自定义 error

let json = '{"age":30}';
try {
  let user = JSON.parse(json);
  console.log(user.name); //没有name
} catch (err) {
  console.log("doesn't execute");
}
'throw'操作符

语法如下:

throw <error object>

在 JavaScript 中有很多内建的标准 error 的构建起:Error、SyntaxError、ReferenceError、TypeError等。

let error = new Error(message);
let error = new SyntaxError(message);
let error = new TypeError(message);

例如:

let error = new Error("Things happen o_O");

console.log(error.name); //Error
console.log(error.message); // Things happen o_O
let json = '{"age":30}';
try {
  let user = JSON.parse(json);

  if (!user.name) {
    throw new SyntaxError("数据不全,缺少name属性");
  }
  console.log(user.name);
} catch (err) {
  console.log("JSON Error: " + err.message); //JSON Error: 数据不全,缺少name属性
}

再次抛出

function readData() {
  let json = '{ "age": 30 }';

  try {
    // ...
    blabla(); // error!
  } catch (err) {
    // ...
    if (!(err instanceof SyntaxError)) {
      throw err; // 再次抛出(不知道如何处理它)
    }
  }
}

try {
  readData();
} catch (err) {
  alert("External catch got: " + err); // 捕获了它!
}

try...catch...finally

try{
  ...尝试执行的代码...
}catch(err){
  ...错误处理...
}finally{
  ...总会执行的代码...
}

finally 和 return

finally子句适用于try...catch的任何出口。 这包括显式的return。

例如:

function f() {
  try {
    return 1;
  } catch (err) {
  } finally {
    console.log("finally");
  }
}

console.log(f()); //先执行finally 再return

全局 catch

window.onerror = function (message, url, line, col, error) {};
  • message:错误信息(字符串)。
  • url:发生错误的脚本 URL(字符串)。
  • line:发生错误的行号(数字)。
  • col:发生错误的列号(数字)。
  • error:Error 对象(对象)。

全局错误处理程序的作用通常不是恢复脚本的执行---一般是用来将错误信息发送给开发者。

自定义 Error,扩展 Error

扩展 Error

需求: 检查 json 格式和数据完整性。

class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = "ValidationError";
  }
}

function test() {
  throw new ValidationError("Whoops!");
}

try {
  test();
} catch (err) {
  console.log(err.name); //ValidationError
  console.log(err.message); //Whoops!
  console.log(err.stack); //ValidationError: Whoops! at test (<anonymous>:9:9) at <anonymous>:13:3
}
//完整版
class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = "ValidationError";
  }
}

function test(json) {
  let user = JSON.parse(json);

  if (!user.age) {
    throw new ValidationError("缺少age属性");
  }

  if (!user.name) {
    throw new ValidationError("缺少name属性");
  }
  return user;
}

try {
  let user = readUser('{"age:25"}');
} catch (err) {
  if (err instanceof ValidationError) {
    console.log("数据格式错误:" + err.message);
  } else if (err instanceof SyntaxError) {
    console.log("JSON格式错误:" + err.message);
  } else {
    throw err;
  }
}

深入继承

class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = "ValidationError";
  }
}

class PropertyRequiredError extends ValidationError {
  constructor(property) {
    super("No property: " + property);
    this.name = "PropertyRequiredError";
    this.property = property;
  }
}

function readUser(json) {
  let user = JSON.parse(json);

  if (!user.age) {
    throw new PropertyRequiredError("age");
  }
  if (!user.name) {
    throw new PropertyRequiredError("name");
  }

  return user;
}

try {
  let user = readUser('{"age":25}');
} catch (err) {
  if (err instanceof ValidationError) {
    console.log("Invalid data: " + err.message); //Invalid data: No property: name
    console.log(err.name); //PropertyRequiredError
    console.log(err.property); //name
  } else if (err instanceof SyntaxError) {
    console.log("JSON Syntax Error: " + err.message);
  } else {
    throw err;
  }
}
class MyError extends Error {
  constructor(message) {
    super(message);
    this.name = this.constructor.name;
  }
}

class ValidationError extends MyError {}

class PropertyRequiredError extends ValidationError {
  constructor(property) {
    super("No property: " + property);
    this.property = property;
  }
}

// name 是对的
alert(new PropertyRequiredError("field").name); // PropertyRequiredError

包装异常

为了解决 在 readUser 函数中的多个 if 判断

  1. 创建一个新的类ReadError来表示一般的"数据读取"error。
  2. 函数readUser将补货内部发生的数据读取 error,例如ValidationError和SyntaxError,并生成一个ReadError来进行替代。
  3. 对象ReadError会把对原始 error 的引用保存在其cause属性中。
class ReadError extends Error {
  constructor(message, cause) {
    super(message);
    this.cause = cause;
    this.name = "ReadError";
  }
}

class ValidationError extends Error {}

class PropertyRequiredError extends ValidationError {}

function validateUser(user) {
  if (!user.age) {
    throw new PropertyRequiredError("age");
  }

  if (!user.name) {
    throw new PropertyRequiredError("name");
  }
}

function readUser(json) {
  let user;
  try {
    user = JSON.parse(json);
  } catch (err) {
    if (err instanceof SyntaxError) {
      throw new ReadError("Syntax Error", err);
    } else {
      throw err;
    }
  }

  try {
    validateUser(user);
  } catch (err) {
    if (err instanceof ValidationError) {
      throw new ReadError("Validation Error", err);
    } else {
      throw err;
    }
  }
}

try {
  readUser("{bad json}");
} catch (e) {
  if (e instanceof ReadError) {
    console.log(e);
    console.log("Original error: " + e.cause);
  } else {
    throw e;
  }
}
最后更新:
贡献者: qiuyulc
Prev
class
Next
Promise