返回顶部
首页 > 资讯 > 精选 >Vue3如何进行全局异常处理
  • 734
分享到

Vue3如何进行全局异常处理

2023-06-29 09:06:26 734人浏览 薄情痞子
摘要

本篇内容主要讲解“vue3如何进行全局异常处理”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue3如何进行全局异常处理”吧!在开发组件库或者插件,经常会需要进行全局异常处理,从而实现:全局统一

本篇内容主要讲解“vue3如何进行全局异常处理”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习Vue3如何进行全局异常处理”吧!

Vue3如何进行全局异常处理

开发组件库或者插件,经常会需要进行全局异常处理,从而实现:

  • 全局统一处理异常;

  • 为开发者提示错误信息;

  • 方案降级处理等等。

那么如何实现上面功能呢?本文先简单实现一个异常处理方法,然后结合 Vue3 源码中的实现详细介绍,最后总结实现异常处理的几个核心。

本文 Vue3 版本为 3.0.11

一、前端常见异常

对于前端来说,常见的异常比较多,比如:

  • js 语法异常;

  • ajax 请求异常;

  • 静态资源加载异常;

  • Promise 异常;

  • iframe 异常;

  • 等等

最常用的比如:

1. window.onerror

通过 window.onerror文档可知,当 JS 运行时发生错误(包括语法错误),触发 window.onerror()

window.onerror = function(message, source, lineno, colno, error) {  console.log('捕获到异常:',{message, source, lineno, colno, error});}

函数参数:

  • message:错误信息(字符串)。可用于html onerror=""处理程序中的 event

  • source:发生错误的脚本URL(字符串)

  • lineno:发生错误的行号(数字)

  • colno:发生错误的列号(数字)

  • error:Error对象(对象)

若该函数返回true,则阻止执行默认事件处理函数。

2.  try...catch 异常处理

另外,我们也经常会使用 try...catch 语句处理异常:

try {  // do something} catch (error) {  console.error(error);}

更多处理方式,可以阅读前面推荐的文章。

3. 思考

大家可以思考下,自己在业务开发过程中,是否也是经常要处理这些错误情况?那么像 Vue3 这样复杂的库,是否也是到处通过 try...catch来处理异常呢?接下来一起看看。

二、实现简单的全局异常处理

在开发插件或库时,我们可以通过 try...catch封装一个全局异常处理方法,将需要执行的方法作为参数传入,调用方只要关心调用结果,而无需知道该全局异常处理方法内部逻辑。大致使用方法如下:

const errorHandling = (fn, args) => {  let result;  try{    result = args ? fn(...args) : fn();  } catch (error){    console.error(error)  }  return result;}

测试一下:

const f1 = () => {    console.log('[f1 running]')    throw new Error('[f1 error!]')}errorHandling(f1);

可以看到,当需要为方法做异常处理时,只要将该方法作为参数传入即可。但是上面示例跟实际业务开发的逻辑差得有点多,实际业务中,我们经常会遇到方法的嵌套调用,那么我们试一下:

const f1 = () => {    console.log('[f1]')    f2();}const f2 = () => {    console.log('[f2]')    f3();}const f3 = () => {    console.log('[f3]')    throw new Error('[f3 error!]')}errorHandling(f1)

这样也是没问题的。那么接下来就是在 errorHandling方法的 catch分支实现对应异常处理即可。接下来看看 Vue3 源码中是如何处理的?

三、Vue3 如何实现异常处理

理解完上面示例,接下来看看在 Vue3 源码中是如何实现异常处理的,其实现起来也是很简单。

1. 实现异常处理方法

errorHandling.ts 文件中定义了 callWithErrorHandlingcallWithAsyncErrorHandling两个处理全局异常的方法。顾名思义,这两个方法分别处理:

  • callWithErrorHandling:处理同步方法的异常;

  • callWithAsyncErrorHandling:处理异步方法的异常。

使用方式如下:

callWithAsyncErrorHandling(  handler,  instance,  ErrorCodes.COMPONENT_EVENT_HANDLER,  args)

代码实现大致如下:

// packages/runtime-core/src/errorHandling.ts// 处理同步方法的异常export function callWithErrorHandling(  fn: Function,  instance: ComponentInternalInstance | null,  type: ErrorTypes,  args?: unknown[]) {  let res  try {    res = args ? fn(...args) : fn(); // 调用原方法  } catch (err) {    handleError(err, instance, type)  }  return res}// 处理异步方法的异常export function callWithAsyncErrorHandling(  fn: Function | Function[],  instance: ComponentInternalInstance | null,  type: ErrorTypes,  args?: unknown[]): any[] {  // 省略其他代码  const res = callWithErrorHandling(fn, instance, type, args)  if (res && isPromise(res)) {    res.catch(err => {      handleError(err, instance, type)    })  }  // 省略其他代码}

callWithErrorHandling方法处理的逻辑比较简单,通过简单的 try...catch 做一层封装。而 callWithAsyncErrorHandling 方法就比较巧妙,通过将需要执行的方法传入 callWithErrorHandling方法处理,并将其结果通过 .catch方法进行处理。

2. 处理异常

在上面代码中,遇到报错的情况,都会通过 handleError()处理异常。其实现大致如下:

// packages/runtime-core/src/errorHandling.ts// 异常处理方法export function handleError(  err: unknown,  instance: ComponentInternalInstance | null,  type: ErrorTypes,  throwInDev = true) {  // 省略其他代码  logError(err, type, contextVnode, throwInDev)}function logError(  err: unknown,  type: ErrorTypes,  contextVNode: VNode | null,  throwInDev = true) {  // 省略其他代码  console.error(err)}

保留核心处理逻辑之后,可以看到这边处理也是相当简单,直接通过 console.error(err)输出错误内容。

3. 配置 errorHandler 自定义异常处理函数

在使用 Vue3 时,也支持指定自定义异常处理函数,来处理组件渲染函数侦听器执行期间抛出的未捕获错误。这个处理函数被调用时,可获取错误信息和相应的应用实例。文档参考:《errorHandler》使用方法如下,在项目 main.js文件中配置:

// src/main.jsapp.config.errorHandler = (err, vm, info) => {  // 处理错误  // `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子}

那么 errorHandler()是何时执行的呢?我们继续看看源码中 handleError() 的内容,可以发现:

// packages/runtime-core/src/errorHandling.tsexport function handleError(  err: unknown,  instance: ComponentInternalInstance | null,  type: ErrorTypes,  throwInDev = true) {  const contextVNode = instance ? instance.vnode : null  if (instance) {    // 省略其他代码    // 读取 errorHandler 配置项    const appErrorHandler = instance.appContext.config.errorHandler    if (appErrorHandler) {      callWithErrorHandling(        appErrorHandler,        null,        ErrorCodes.APP_ERROR_HANDLER,        [err, exposedInstance, errorInfo]      )      return    }  }  logError(err, type, contextVNode, throwInDev)}

通过 instance.appContext.config.errorHandler取到全局配置的自定义错误处理函数,存在时则执行,当然,这边也是通过前面定义的 callWithErrorHandling来调用。

4. 调用 errorCaptured 生命周期钩子

在使用 Vue3 的时候,也可以通过 errorCaptured生命周期钩子来捕获来自后代组件的错误。 如下:

(err: Error, instance: Component, info: string) => ?boolean

此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false阻止该错误继续向上传播。有兴趣的同学可以通过文档,查看具体的错误传播规则。使用方法如下,父组件监听 onErrorCaptured生命周期(示例代码使用 Vue3 setup 语法):

<template>  <Message></Message></template><script setup>// App.vue  import { onErrorCaptured } from 'vue';  import Message from './components/Message.vue'  onErrorCaptured(function(err, instance, info){  console.log('[errorCaptured]', err, instance, info)})</script>

子组件如下:

<template>  <button @click="sendMessage">发送消息</button></template><script setup>// Message.vueconst sendMessage = () => {  throw new Error('[test onErrorCaptured]')}</script>

当点击「发送消息」按钮,控制台便输出错误:

[errorCaptured] Error: [test onErrorCaptured]    at Proxy.sendMessage (Message.vue:36:15)    at _createElementVNode.onClick._cache.<computed>._cache.<computed> (Message.vue:3:39)    at callWithErrorHandling (runtime-core.esm-bundler.js:6706:22)    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:6715:21)    at HTMLButtonElement.invoker (runtime-dom.esm-bundler.js:350:13) Proxy {sendMessage: ƒ, …} native event handler

可以看到 onErrorCaptured生命周期钩子正常执行,并输出子组件 Message.vue内的异常。

那么这个又是如何实现呢?还是看 errorHandling.ts 中的 handleError() 方法:

// packages/runtime-core/src/errorHandling.tsexport function handleError(  err: unknown,  instance: ComponentInternalInstance | null,  type: ErrorTypes,  throwInDev = true) {  const contextVNode = instance ? instance.vnode : null  if (instance) {    let cur = instance.parent    // the exposed instance is the render proxy to keep it consistent with 2.x    const exposedInstance = instance.proxy    // in production the hook receives only the error code    const errorInfo = __DEV__ ? ErrorTypeStrings[type] : type    while (cur) {      const errorCapturedHooks = cur.ec // ①取出组件配置的 errorCaptured 生命周期方法      if (errorCapturedHooks) {        // ②循环执行 errorCaptured 中的每个 Hook        for (let i = 0; i < errorCapturedHooks.length; i++) {          if (            errorCapturedHooks[i](err, exposedInstance, errorInfo) === false          ) {            return          }        }      }      cur = cur.parent    }    // 省略其他代码  }  logError(err, type, contextVNode, throwInDev)}

这边会先获取 instance.parent作为当前处理的组件实例进行递归,每次将取出组件配置的 errorCaptured 生命周期方法的数组并循环调用其每一个钩子,然后再取出当前组件的父组件作为参数,最后继续递归调用下去。

5. 实现错误码和错误消息

Vue3 还为异常定义了错误码和错误信息,在不同的错误情况有不同的错误码和错误信息,让我们能很方便定位到发生异常的地方。错误码和错误信息如下:

// packages/runtime-core/src/errorHandling.tsexport const enum ErrorCodes {  SETUP_FUNCTION,  RENDER_FUNCTION,  WATCH_GETTER,  WATCH_CALLBACK,  // ... 省略其他}export const ErrorTypeStrings: Record<number | string, string> = {  // 省略其他  [LifecycleHooks.RENDER_TRACKED]: 'renderTracked hook',  [LifecycleHooks.RENDER_TRIGGERED]: 'renderTriggered hook',  [ErrorCodes.SETUP_FUNCTION]: 'setup function',  [ErrorCodes.RENDER_FUNCTION]: 'render function',  // 省略其他  [ErrorCodes.SCHEDULER]:    'scheduler flush. This is likely a Vue internals bug. ' +    'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/vue-next'}

当不同错误情况,根据错误码 ErrorCodes来获取 ErrorTypeStrings错误信息进行提示:

// packages/runtime-core/src/errorHandling.tsfunction logError(  err: unknown,  type: ErrorTypes,  contextVNode: VNode | null,  throwInDev = true) {  if (__DEV__) {    const info = ErrorTypeStrings[type]    warn(`Unhandled error${info ? ` during execution of ${info}` : ``}`)    // 省略其他  } else {    console.error(err)  }}

6. 实现 Tree Shaking

关于 Vue3 实现 Tree Shaking 的介绍,可以看我之前写的高效实现框架和 JS 库瘦身。其中,logError 方法中就使用到了:

// packages/runtime-core/src/errorHandling.tsfunction logError(  err: unknown,  type: ErrorTypes,  contextVNode: VNode | null,  throwInDev = true) {  if (__DEV__) {    // 省略其他  } else {    console.error(err)  }}

当编译成 production 环境后,__DEV__分支的代码不会被打包进去,从而优化包的体积。

到此,相信大家对“Vue3如何进行全局异常处理”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: Vue3如何进行全局异常处理

本文链接: https://lsjlt.com/news/324206.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Vue3如何进行全局异常处理
    本篇内容主要讲解“Vue3如何进行全局异常处理”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue3如何进行全局异常处理”吧!在开发组件库或者插件,经常会需要进行全局异常处理,从而实现:全局统一...
    99+
    2023-06-29
  • Vue3动态组件如何进行异常处理
    这篇“Vue3动态组件如何进行异常处理”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Vue3动态组件如何进行异常处理”文章吧...
    99+
    2023-07-04
  • Node.js全局处理响应并进行异常管理
    目录中间件设计模式--"洋葱模型"Node.js中全局处理响应使用Koa创建应用中间件设计模式--"洋葱模型" 在Node.js中,可以使用中...
    99+
    2023-05-17
    Node.js 全局处理异常管理 Node.js 全局响应
  • ASP.NETCore全局异常处理
    一、前言 在程序设计中,我们会遇到各种各样的异常问题,一个好的异常处理解决方案能够帮助开发者快速的定位问题,也能够给用户更好的用户体验。那么我们在AspNetCore中该如何捕获和处...
    99+
    2024-04-02
  • 如何使用SpringBoot处理全局异常
    如何使用SpringBoot处理全局异常 使用@ControllerAdvice 和 @ExceptionHandler处理全局异常 参考: @ControllerAdvice@ResponseBod...
    99+
    2023-10-27
    spring boot java 后端 异常处理
  • Spring Boot如何统一处理全局异常
    这篇文章给大家分享的是有关Spring Boot如何统一处理全局异常的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。注解的介绍@ControllerAdvice@ControllerAdvice注解是Sp...
    99+
    2023-06-22
  • SpringBoot全局异常处理 | Java
    ⭐简单说两句⭐ 作者:后端小知识 CSDN个人主页:后端小知识 🔎GZH:后端小知识 🎉欢迎关注🔎点赞👍收藏⭐️留言...
    99+
    2023-10-12
    java spring boot 后端
  • Java Springboot全局异常处理
    目录前言一、思路?二、步骤1.自定义接口:2.自定义错误枚举3.自定义异常类4.异常捕获5.在代码中抛异常总结前言 对于作为菜鸟程序员的我来说,经常在controller使用try-...
    99+
    2024-04-02
  • Java中如何实现Springboot全局异常处理
    这篇文章主要为大家展示了“Java中如何实现Springboot全局异常处理”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java中如何实现Springboot全局异常处理”这篇文章吧。一、思路...
    99+
    2023-06-25
  • SpringBoot全局异常处理方式
    目录SpringBoot全局异常处理springboot全局异常处理——@ControllerAdvice+ExceptionHandler一、全局捕获异常后,返回json给浏览器二...
    99+
    2024-04-02
  • springboot全局异常处理详解
    一、单个controller范围的异常处理package com.xxx.secondboot.web;import org.springframework.web.bind.annotation.ExceptionHandler;impo...
    99+
    2023-05-31
    spring boot 全局异常
  • 如何在Python中进行异常处理
    目录一、抛出异常和自定义异常1、raise语句2、自定义异常类型二、捕捉异常1、捕捉多个异常2、获取异常信息三、finally子句一、抛出异常和自定义异常 Python中使用用异常对...
    99+
    2024-04-02
  • springboot如何实现全局异常处理及自定义异常类
    这篇文章主要介绍springboot如何实现全局异常处理及自定义异常类,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!全局异常处理及自定义异常类全局异常处理定义一个处理类,使用@ControllerAdvice注解。@...
    99+
    2023-06-29
  • 浅析Vue3动态组件怎么进行异常处理
    Vue3动态组件怎么进行异常处理?下面本篇文章带大家聊聊Vue3 动态组件异常处理的方法,希望对大家有所帮助!【相关推荐:vuejs视频教程】动态组件有两种常用场景:一是动态路由:// 动态路由 export const asyncRout...
    99+
    2023-05-14
    前端 Vue.js JavaScript
  • Django RestFramework 全局异常处理详解
    目录RESTframework定义的异常一、定义异常处理类二、注册DRF框架中默认的错误处理为自己定义的类总结REST framework定义的异常 APIException 所有异...
    99+
    2024-04-02
  • Spring Boot全局异常处理解析
    本文为大家分享了Spring Boot全局异常处理,供大家参考,具体内容如下1、后台处理异常a、引入thymeleaf依赖<!-- thymeleaf模板插件 --><dependency> <groupId&...
    99+
    2023-05-31
    spring boot 异常处理
  • SpringBoot中如何进行统一异常处理
    目录1、处理前2、进行系统异常全局处理3、进行自定义异常处理总结如何在SpringBoot项目里进行统一异常处理 需要了解的知识 @ControllerAdvice的作用 1、处理前...
    99+
    2024-04-02
  • 如何在Spring Boot中进行异常处理
    这篇文章将为大家详细讲解有关如何在Spring Boot中进行异常处理,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。通过这篇文章,可以搞懂如何在 Sprin...
    99+
    2024-04-02
  • 如何进行C++代码的异常处理?
    如何进行C++代码的异常处理引言:在编写C++代码时,异常处理是非常重要的一部分。异常处理机制可以帮助我们在程序运行时捕获和处理错误。在本文中,我们将讨论一些关于如何在C++中进行异常处理的重要概念和技巧。一、异常处理的基本概念异常处理是一...
    99+
    2023-11-02
    代码 C++ 异常处理
  • C++ 函数库如何进行异常处理?
    c++++ 函数库异常处理通过 try-catch 语句实现,可捕获异常类型并进行处理。常见异常类型包括逻辑错误、运行时错误、内存分配失败、类型转换失败、索引超范围。实战案例演示了文件读...
    99+
    2024-04-18
    c++ 异常处理 标准库
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作