Java教程

JavaScript 错误处理

本文主要是介绍JavaScript 错误处理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

JavaScript 错误处理

错误处理对于今天复杂的 Web 应用程序开发而言至关重要。不能提前预测到可能发生的错误,不能提前采取恢复策略,可能导致较差的用户体验,最终引发用户不满。多数浏览器默认情况下都不会向用户报告错误,因此在开发和调试期间需要启用浏览器的错误报告功能。然而,在投入运行的产品代码中,则不应该再有诸如此类的错误报告。

摘自——《JavaScript 高级程序设计语言(第 3 版)》

正如上面所说,JavaScript 错误处理的最终目的是——防止 JavaScript 错误的产生影响了用户的体验。

要实现这个目的,可以从以下两个方面出发:

  • 当发生错误时,可以让用户平缓的渡过错误
  • 在代码上尽可能的避免错误的发生

让用户平缓的渡过错误

“让用户平缓的渡过错误”,说白了就是当发生错误时,要对错误做出友好的处理。

要做到这一点,我们就需要捕捉错误。有如下两种方法:

try - catch

在可能发生错误的地方时使用 try-catch语句。

用法如下:

try {
  // 可能发生错误的代码
} catch (error){
  // 发生错误时处理的代码
}

借助 try-catch 语句,我们就可以捕捉错误信息并及时作出相应的处理了。

window.onerror 事件

window.onerror 事件可以接收try-catch未处理的所有错误。

window.onerror 事件默认三个传参数:

  • msg: 错误信息
  • url: 错误所在文件
  • line: 错误所在的代码行

用法如下:

window.onerror = function(msg, url, lin){
  console.log(msg)
}

window.onerror 是避免浏览器报告错误的最后一道防线,理想情况下,只要可能就不应该使用它。只要能够适当的使用 try-catch语句,就不会有错误提交给浏览器,也就不会触发 error 事件。

摘自——《JavaScript 高级程序设计语言(第 3 版)》

在代码上尽可能的避免错误的发生

除了要做“事后诸葛亮”,我们也要做到“未卜先知”,在编写代码时就要尽可能的避免错误的产生。

在 JavaScript 中发生错误的主要原因如下:

  • 类型转换错误
  • 数据类型错误
  • 通讯错误

类型转换错误

这个主要发生在数据类型隐性转换上。如下:

alert(5 == '5'); // true
alert(5 === '5'); // false

function concat(str1, str2, str3){
	let result = str1 + str2;
  if(str3){		// 绝对不要这样子!!! 如果 str3 时一个数组,同样也为 true
    result += str3;
  }
  
  return result;
}

为了避免数据类型隐性转换错误的出现。有如下建议:

  • 不使用 ==!=,转而使用===!==
  • 不使用隐性转换true/false来判断值是否为空
  • 不使用隐性转换来判断true/false

数据类型错误

JavaScript 是松散类型的语言,数据类型是可以随时变换的,在使用变量和函数参数前,不会对数据类型的正确性做判断。因为这种“高度自由”,我们很有可能将错误的类型数据传递给函数,导致数据类型错误的产生。如下:

// 不安全的函数,任何非数组值都会导致错误
function reverswSort(values){
	if(values){	// 绝对不要这样!!!
		values.sort();
    value.reverse();
  }
}

为了避免这种可能存在的错误,我们最好对函数参数的数据类型进行检测。

// 安全,非数组值将被忽略
function reverswSort(values){
	if(values instanceof Array){
		values.sort();
    value.reverse();
  }
}

通讯错误

通讯错误值的是 HTTP 请求的错误。常见的有三种:

  • url 错误
  • 参数错误
  • 回传数据出错
  • 后台服务器出错

一、三点没什么好说的,只要前后端开发人员做好沟通,API 文档写好、写全就可以最大程度的避免了。对于传参错误,一般发生在参数的数据类型出错上。所以为了避免参数错误,我们也需要做一些必要的数据类型检测。

关于后台服务器错误,这个是前端无法提前规避的。前端只能在发生这个错误后做出相应友好的处理。常见的 HTTP 请求错误有:

状态码状态码英文名称中文描述
400Bad Request客户端请求的语法错误,服务器无法理解
401Unauthorized请求要求用户的身份认证
403Forbidden服务器理解请求客户端的请求,但是拒绝执行此请求
404Not Found服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
408Request Time-out服务器等待客户端发送的请求时间过长,超时
410Gone客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
500Internal Server Error服务器内部错误,无法完成请求
502Bad Gateway作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503Service Unavailable由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504Gateway Time-out充当网关或代理的服务器,未及时从远端服务器获取请求
505HTTP Version not supported服务器不支持请求的HTTP协议的版本,无法完成处理

更多 HTTP 状态码可查看:HTTP状态码

调试——错误信息的输出

前面提到的两个出发点——“让用户平缓的渡过错误”和“在代码上尽可能的避免错误的发生”,一个是着眼于错误发生后一个是着眼于错误发生时的处理。好的代码应该是让代码不要产生错误才对。也就是说,我们需要解决错误的产生。如前面的例子:

function reverswSort(values){
	if(values instanceof Array){
		values.sort();
    value.reverse();
  }
}

这里产生错误的原因是因为开发人员错误参数导致的。尽管这里的代码避免了错误的产生,但是如果不告知该开发者,他以后还是可能用错的。所以,我们还需要将错误了产生原因通知开发人员。也就是输出错误信息。这里推荐两种处理方法:

  • 使用console.log 输出控制台
  • 使用 throw 抛出错误到控制台。throw 会终止代码的运行。
// 使用console.log 输出控制台
function reverswSort(values){
  if(values instanceof Array){
		values.sort();
    value.reverse();
  }else{
    console.log('reverswSort(): 参数数据类型错误,应传递一个数组!');
  }
}

// 使用 throw 抛出错误到控制台
function reverswSort(values){
	if(values instanceof Array){
		values.sort();
    value.reverse();
  }else{
    throw new Error('reverswSort(): 参数数据类型错误,应传递一个数组!');
  }
}

对于大型应用程序来说,自定义的错误通常都使用 assert() 函数抛出。这个函数接受两个参数,一个是求值结果应为 true 的条件,另外一个是条件为 false 是抛出的错误。以下就是一个非常基础的 assert() 函数。

function assert(condition, message){
	if(!condition){
		throw new Error(message);
  }
}

摘自——《JavaScript 高级程序设计语言(第 3 版)》

以上就是关于 Javascript 错误处理的介绍了。本文主要参考了《JavaScript 高级程序设计语言(第 3 版)》第 17 章 错误处理与调试。算是对该章节的一个粗浅总结吧!



console、assert 分享

/**
 * console 模块提供将信息打印到控制台的 class,包含错误信息抛出类 Assert、日志打印类 Logger
 * @module console
 */

/**
 * Assert 类:用于对外抛出错误下信息,并终止当前执行代码
 * @class
 */
class Assert {
  /**
   * @constructs
   * @param {Boolean} condition — 必填,当值为 false 时,将执行 throw
   * @param {String} msg - 必填,throw 的错误信息
   */
  constructor(condition, msg) {
    if (typeof condition !== 'boolean') {
      this.throwMsg('class Assert——构造函数参数 condition 数据类型错误,需为 Boolean');
    }
    if (typeof msg !== 'string') {
      this.throwMsg('class Assert——构造函数参数 condition 数据类型错误,需为 String');
    }
    if (!condition) {
      console.log('%c BOSS3.0 %c 报错日志 %c', 'background:#35495E; padding: 1px; border-radius: 3px 0 0 3px; color: #fff;', 'background: #ed4014; padding: 1px; border-radius: 0 3px 3px 0;  color: #fff;', 'background:transparent');
      throw new Error(msg);
    }
  }

  /**
   * 抛出错误信息
   * @function throwMsg
   * @param {string} msg - 错误信息
   */
  throwMsg(msg) {
    console.log('%c BOSS3.0 %c 报错日志 %c', 'background:#35495E; padding: 1px; border-radius: 3px 0 0 3px; color: #fff;', 'background: #ed4014; padding: 1px; border-radius: 0 3px 3px 0;  color: #fff;', 'background:transparent');
    throw new Error(msg);
  }
}

/**
 * Logger 类:用于向控制台打印信息,不会终止代码运行
 * @class Logger
 */
class Logger {
  colorMap = {
    info: '#2d8cf0',
    warn: '#ff9900',
    error: '#ed4014'
  };

  /**
   * 构造函数
   * @constructs
   * @param {String} msg - 必填,要打印的信息
   * @param { String } type - 必填,信息类型。可选值:info、warn、error
   * @param {Object|String} detail - 可选,详情
   */
  constructor(msg, type, detail) {
    if (typeof msg !== 'string') {
      new Assert(false, 'class Logger——构造函数参数 condition 数据类型错误,需为 String');
    }
    if (!Object.keys(this.colorMap).includes(type)) {
      new Assert(false, 'class Logger——构造函数参数 type 值错误,可选值为:info、warn、error');
    }
    this.msg = msg;
    this.type = type;
    this.detail = detail;
    this.log();
  }

  /**
   * 日志打印
   * @function log
   */
  log() {
    console.log('%c BOSS3.0 %c 日志内容 %c', 'background:#35495E; padding: 1px; border-radius: 3px 0 0 3px; color: #fff;', 'background:'.concat(this.colorMap[this.type], '; padding: 1px; border-radius: 0 3px 3px 0;  color: #fff;'), 'background:transparent');
    console.group('完整日志');
    console.log('message: ' + this.msg);
    console.log('time:    ' + new Date().toLocaleString());
    console.log('type:    ' + this.type);
    console.log('detail:  %O', this.detail);
    console.groupEnd();
  }
}

export { Assert, Logger };

参考文献

  • 《JavaScript 高级程序设计语言(第 3 版)》
  • 《HTTP状态码》
这篇关于JavaScript 错误处理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!