前端异常信息处理规范

前端异常信息处理规范

Created
Aug 21, 2023 03:49 AM
Tags
前端异常信息处理规范是一套旨在规范前端应用程序在出现异常情况时的处理方式的准则和指南。在现代的复杂前端应用中,异常情况不可避免地会发生,可能涉及网络请求失败、数据验证错误、未处理的 Promise 拒绝等等。为了保证应用的稳定性、用户体验和开发效率,制定一份明确的异常处理规范是至关重要的。
 
作用:
前端异常信息处理规范的作用在于:
  1. 提供一致的用户体验: 通过统一的异常处理方式,确保用户在遇到问题时能够得到一致、友好的用户反馈,增强用户满意度。
  1. 保障应用稳定性: 规范的异常处理能够帮助应对异常情况,减少应用崩溃或不可预测行为的发生,从而提高应用的稳定性。
  1. 加速问题定位和解决: 统一的异常处理方式和记录错误信息的做法有助于开发团队更快速地定位和解决问题,提高开发效率。
  1. 增强代码质量: 通过正确处理异常情况,避免未捕获的异常,提高代码的健壮性和可维护性。
  1. 促进团队合作: 规范的异常处理方式可以在团队内建立一致的理解和共识,促进开发团队之间的合作和沟通。
  1. 方便后续维护: 随着项目的演进,异常处理规范可以作为项目的一部分持续维护和改进,确保应用在不同阶段都能够有效地应对异常情况。
  1. 提升用户信任: 在用户遇到问题时,透明地展示错误信息和解决方法建议,能够增加用户对应用的信任度。

1.统一的异常处理入口

  • 定义一个异常处理模块,导出一个异常处理方法,例如:
    • // errorHandler.js
      
      export default handleError;
      
      function handleError(err) {
        // 处理逻辑
      }
      
  • 在项目入口文件中导入该模块,并注册全局错误处理:
    • // main.js
      
      import errorHandler from './errorHandler';
      
      window.onerror = function(event) {
        errorHandler(event);
      };
      
      window.addEventListener('unhandledrejection', errorHandler);
      
  • Promise的reject以及异步代码的catch也交给该方法处理:
    • fetchData()
        .catch(errorHandler);
      
      asyncFunction()
        .catch(errorHandler);
      
  • 组件级别的错误使用Error Boundary包裹,交给该方法处理
  • 定义不同的日志上报级别,区分不同类型错误的处理
  • 记录必要的日志,包括错误堆栈、URL、时间等
  • 根据错误级别进行日志上报,分别上报至不同接口
  • 对接口异常进行统一处理,避免代码中混杂try catch
  • 考虑接入sentry、fundebug等平台进行异常监控

2. 区分错误等级

  • 将错误分为致命(Fatal)错误和普通(Regular)错误
  • 致命错误会导致应用无法继续运行,需要优先处理,例如:
    • 编译期错误
    • 服务端返回5xx错误
    • JavaScript运行错误
    • 无网络连接
    • 访问控制错误
    • 证书错误
  • 普通错误不会影响应用运行,可以正常处理,例如:
    • 404页面不存在 -接口超时
    • 业务异常错误
  • 定义错误代码规范:
    • 1xx信息提示
    • 2xx成功
    • 3xx重定向
    • 4xx客户端错误
    • 5xx服务器错误
  • 根据错误代码判断错误级别
  • 配置致命错误的自动恢复方案:
    • 定时重试请求
    • 提示用户重新加载
    • 打开某些备用功能
  • 对不同级别错误采用不同的处理策略:
    • 致命错误优先修复
    • 普通错误记录日志,定期分析

3. 详细的错误信息

  • 错误日志需要包含详尽信息,方便定位问题
  • 基础信息:
    • 错误名称/类型
    • 错误消息
    • 错误代码
    • 错误堆栈
    • 发生时间
  • 环境信息:
    • 浏览器类型和版本
    • 操作系统
    • Node环境版本
    • 网络类型
    • URL地址
    • 用户代理信息
  • 用户信息:
    • 用户ID
    • 用户名
    • 用户操作步骤
  • 应用状态:
    • 当前路由
    • 页面状态
    • 网络请求状态
    • 本地存储信息
  • 其他信息:
    • 接口参数
    • 前端配置信息
    • 预期结果与实际结果对比
    • 可复现步骤
  • 遵循隐私和安全规范,不记录敏感用户信息
  • 统一接口,分级别上报日志
  • 根据错误信息定期分析、提炼、改进

4. 自定义错误类

  • 可以定义错误基类和多个子类表示不同错误
  • 基类错误:
    • class AppError extends Error {
      
        constructor(message) {
          super(message);
          this.name = this.constructor.name;
        }
      
      }
      
  • 子类继承基类:
    • class TimeoutError extends AppError {
      
        constructor(message) {
          super(message);
          this.name = 'TimeoutError';
          this.code = 1001;
        }
      
      }
      
  • 每种错误区分代码,便于识别
    • 1xx 信息
    • 2xx 成功
    • 3xx 重定向
    • 4xx 请求错误
    • 5xx 服务器错误
  • 错误类包含必要信息:
    • code: 错误代码
    • message: 文字信息
    • stack: 调用栈
    • data: 附加信息
  • 抛出错误实例:
    • throw new TimeoutError("Request timeout");
      
  • catch时可以根据错误类型处理:
    • try {
        // request
      } catch(e) {
        if (e instanceof TimeoutError) {
          // handle timeout
        }
      }
      
  • 统一交给异常处理函数,分门别类上报

5.规范的日志格式

  • 日志采用 JSON 格式,而不是纯文本
  • 每条日志应包含的字段:
    • timestamp - 时间戳
    • level - 日志级别(debug、info、warn、error)
    • message - 日志内容
    • stack - 堆栈踪迹(如果有)
    • url - 当前页面地址
    • method - 请求方法
    • params - 请求参数 (处理过的,不要明文密码等敏感信息)
    • username - 用户名
    • userAgent - 用户代理信息
    • env - 运行环境(开发/测试/生产)
  • 示例:
    • {
        "timestamp": "2019-10-01T12:18:35.947Z",
        "level": "error",
        "message": "请求超时",
        "stack": "TimeoutError: 请求超时 at fetchData",
        "url": "/home",
        "method": "GET",
        "params": {
          "page": 1,
          "size": 10
        },
        "username": "张三",
        "userAgent": "Chrome 75 / Mac OS X 10.14",
        "env": "development"
      }
      
  • 该格式容易被系统解析
  • 可视化及检索更方便
  • 通过日志分析工具分析统计

6.接入异常监控平台

  • 使用sentry、fundebug等成熟平台,获得更多异常数据分析能力
  • 集成SDK,自动捕获前端未处理异常
  • 设置字段映射,将自定义错误日志映射到平台字段
  • 在平台设置异常告警规则
  • 当发生某类致命错误时,平台可以及时通知相关人员
  • 通过平台分析异常类型、数量变化趋势
  • 定位高频次异常,进行优先修复
  • 平台提供错误统计、用户影响等数据报表
  • 不同环境集成不同的监控平台项目
  • 开发环境完整收集堆栈、调试数据
  • 生产环境可屏蔽部分敏感字段,防止泄露
  • 按照平台最佳实践进行配置,保证数据收集的质量

7.分类上报异常信息

  • 根据错误类型,选择合适的上报方式
  • 区分不同类型错误:
    • JavaScript执行错误
    • 资源加载失败
    • 接口错误
    • Promise拒绝错误
    • 跨域、鉴权等访问错误
  • 区分不同级别错误:
    • 普通错误
    • 警告
    • 致命错误
  • 对于异步代码错误,需要通过try-catch处理后再上报
  • 根据类型定义不同的上报接口:
    • /api/jsError
    • /api/resourceError
    • /api/ajaxError
    • /api/promiseError
  • 根据级别定义不同的处理逻辑:
    • 普通错误记录日志
    • 警告错误通知相关人员
    • 致命错误报警、自动恢复
  • 合理设置上报频率,避免重复上报
  • 校验上报接口的响应,保证数据不丢失
  • 按分类统计错误数据,分析各类异常情况

8. 处理异常

以下是对每个错误码的详细描述,以及可能的处理方法和用户反馈建议:

8.1 下载失败

描述: 表示下载资源或文件时出现了错误,可能是网络连接中断、资源不存在等问题。
处理方法: 在下载失败后,可以尝试重新下载,检查网络连接,或者通知用户检查资源是否可用。
用户反馈建议: "下载失败,请检查您的网络连接,然后重试。如果问题仍然存在,请联系我们的客户支持。"
提示方式: 在下载失败时,可以显示一个带有重试按钮的通知栏,让用户可以轻松地重新尝试下载。

8.2 服务器错误

描述: 表示后端服务器在处理请求时发生了错误,可能是服务器崩溃、数据库异常等。
处理方法: 无法直接处理服务器错误,可以尝试重新刷新页面,或者等待一段时间再次尝试。
用户反馈建议: "服务器出现错误,请稍后再试。如果问题持续存在,请联系我们的技术团队。"
提示方式: 可以在页面上展示一个错误提示框,通知用户服务器发生了错误,建议用户刷新页面或稍后再试。

8.3 网络异常

描述: 表示在网络通信过程中出现异常,可能是连接超时、DNS 解析失败等。
处理方法: 检查网络连接是否稳定,或者尝试刷新页面。
用户反馈建议: "网络连接异常,请检查您的网络设置或稍后再试。"
提示方式: 当检测到网络异常时,可以显示一个横幅或浮层,提示用户检查网络连接并提供一个刷新按钮。

8.4 空状态

描述: 表示页面或组件处于空状态,没有相关数据或内容展示。
处理方法: 根据不同的场景,可以提示用户添加数据、前往其他页面,或者提供相关操作。
用户反馈建议: "当前没有可用数据。您可以添加新内容或前往其他页面浏览。"
提示方式: 对于空状态,可以显示一个友好的图片或图标,搭配一个醒目的文字,告知用户当前没有相关数据。

8.5 表单类异常

描述: 表示用户提交的表单数据存在问题,可能是格式错误、必填项未填写等。
处理方法: 在前端对用户输入进行验证,提供清晰的错误提示信息。
用户反馈建议: "提交的表单存在错误,请检查并修正所需的信息。"
提示方式: 在用户提交不合法表单时,可以在错误的输入框下方显示红色文字,清晰地指出出错的地方,并提供错误信息。

8.6 时效性

描述: 表示某个操作或请求的时效已过,可能是验证码过期、链接已失效等。
处理方法: 需要用户重新请求或重新获取相关信息。
用户反馈建议: "操作的时效已过,请重新请求或获取最新的信息。"
提示方式: 对于时效性问题,可以显示一个提示信息,明确告知用户操作已超时,并提供相应的重新获取或刷新操作。

8.7 限定值

描述: 表示某个操作受到限定,可能是字符长度超出限制、数量超过限制等。
处理方法: 提示用户进行调整,以满足操作的限制条件。
用户反馈建议: "操作受到限制,请确保输入的内容符合要求。"
提示方式: 在操作受限时,可以在用户尝试操作的地方显示一个浮层,提示操作受到限制,并解释为什么操作受限。

8.8 不可用

描述: 表示某个功能或服务当前不可用,可能是维护中、功能未开放等。
处理方法: 提醒用户当前功能不可用,提供其他可用的选项。
用户反馈建议: "抱歉,此功能目前不可用。您可以尝试其他功能或稍后再试。"
提示方式: 对于不可用的功能,可以在相关入口处显示一个灰色不可点击的状态,并为用户提供一个信息提示,说明功能不可用原因。

8.9 账号过期

描述: 表示用户的账号或权限已过期,无法继续操作。
处理方法: 提醒用户账号已过期,提供续期或更新账号的方式。
用户反馈建议: "您的账号已过期,请联系我们的客户支持以获取更多信息。"
提示方式: 在账号过期时,可以显示一个特别的通知,提醒用户账号已过期,同时提供续期或更新账号的链接。

8.10 选项不可选

描述: 表示某个选项当前不可选中,可能是由于条件不满足等原因。
处理方法: 提供用户更多信息,解释为什么选项不可选,以及如何满足条件。
用户反馈建议: "很抱歉,此选项当前不可选。请检查相关条件是否满足,或查看提示以获取更多信息。"
提示方式: 当某个选项不可选时,可以将不可选项置灰,并在用户尝试点击时显示一个信息提示,解释为什么选项不可选,提供更多信息。
通过这些描述和用户反馈建议,您可以更好地向用户解释每种异常情况的原因,以及可能的处理方法。这有助于提供更友好和详细的用户体验,使用户能够更好地应对不同的异常情况。

9. 前后端错误码映射规范

前端和后端错误码映射机制旨在建立前后端之间异常信息的标准化映射关系,以便在错误发生时,前端能够根据后端返回的错误码快速识别错误类型并采取适当的处理措施。这种映射机制有助于提高开发效率、减少沟通成本,并提供一致的用户体验。
以下是一套前后端错误码映射机制的简要定义和步骤:

9.1定义:

前后端错误码映射机制是一种标准化的对应关系,将后端返回的错误码映射到前端的特定错误类型,以及相应的用户反馈和处理逻辑。

9.2步骤:

9.2.1错误码约定

前后端团队共同约定一套错误码,用于表示不同类型的错误。错误码可以分为不同的范围或分类,以便更清晰地识别错误类型。

9.2.2错误码映射表:

创建一个前后端错误码映射表,其中列出了后端返回的错误码与前端错误类型的对应关系。映射表可以使用 JSON 格式,如:
{
  "1001": "NETWORK_ERROR",
  "2001": "VALIDATION_ERROR",
  "3001": "AUTH_ERROR",
  // ...
}

9.2.3前端错误类型定义

在前端代码中定义与错误码对应的错误类型。
const ERROR_TYPES = {
  NETWORK_ERROR: 'NETWORK_ERROR',
  VALIDATION_ERROR: 'VALIDATION_ERROR',
  AUTH_ERROR: 'AUTH_ERROR',
  // ...
};

9.2.4错误处理逻辑:

在前端处理网络请求的过程中,根据后端返回的错误码,从映射表中找到对应的前端错误类型,然后执行相应的处理逻辑。
fetch('<https://api.example.com/data>')
  .then(response => {
    if (!response.ok) {
      const errorType = ERROR_MAPPING[response.status];
      handleError(errorType);
    }
    return response.json();
  })
  .catch(error => {
    handleError('NETWORK_ERROR');
  });

9.2.5用户反馈和界面显示:根据错误类型,向用户提供相应的错误信息和界面反馈。这可以通过统一的错误信息显示组件来实现。

通过前后端错误码映射机制,前端开发人员能够更直观地了解后端返回的错误,并根据映射关系进行统一的处理。这有助于加快问题定位、减少误解,同时提供更一致的用户体验。在此机制的基础上,团队还可以根据实际需要进行进一步的优化和扩展。
 

前后端错误码对照表

 
notion image