Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to handle global exceptions in Vue3

2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly explains "how to handle global exceptions in Vue3". Interested friends may wish to have a look at it. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "how Vue3 handles global exceptions".

In the development of component libraries or plug-ins, global exception handling is often required to achieve:

Globally uniformly handle exceptions

Prompt error messages for developers

The scheme is downgraded and so on.

So how to achieve the above functions? This paper first simply implements an exception handling method, then introduces in detail the implementation in the Vue3 source code, and finally summarizes several cores of exception handling.

The Vue3 version of this article is 3.0.11

Common anomalies at the front end

For the front end, there are many common exceptions, such as:

JS syntax exception

Ajax request exception

Static resource loading exception

Promise exception

Iframe exception

Wait

The most commonly used ones are:

1. _ window.onerror

As you can see from the _ window.onerror document, when an error (including syntax error) occurs while JS is running, _ window.onerror () is triggered:

_ window.onerror = function (message, source, lineno, colno, error) {console.log ('catch exception:', {message, source, lineno, colno, error});}

Function parameters:

Message: error message (string). Can be used for event in the HTML onerror= "" handler.

Source: the script URL in which the error occurred (string)

Lineno: line number (number) on which the error occurred

Colno: column number (number) in which the error occurred

Error:Error object (object)

If the function returns true, the default event handler is blocked.

2. Try...catch exception handling

In addition, we often use try...catch statements to handle exceptions:

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

For more ways to deal with it, you can read the previously recommended article.

3. Thinking

You can think about whether you often have to deal with these errors in the process of business development. So is it true that libraries as complex as Vue3 handle exceptions everywhere through try...catch? Let's take a look next.

Second, implement simple global exception handling

When developing a plug-in or library, we can encapsulate a global exception handling method through try...catch, passing in the method that needs to be executed as parameters, and the caller only needs to care about the call result without knowing the internal logic of the global exception handling method. The general usage is as follows:

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

Test it:

Const F1 = () = > {console.log ('[F1 running]') throw new Error ('[F1 error!]')} errorHandling (F1); / * output: [F1 running] Error: [F1 error!] At F1 (/ Users/wangpingan/leo/www/node/www/a.js:14:11) at errorHandling (/ Users/wangpingan/leo/www/node/www/a.js:4:39) at Object. (/ Users/wangpingan/leo/www/node/www/a.js:17:1) at Module._compile (node:internal/modules/cjs/loader:1095:14) at Object.Module._extensions..js (node:internal/modules/cjs/loader:1147:10) at Module.load (node:internal/modules/cjs/loader:975:32) at Function.Module._load (node:internal/modules/cjs/loader:822:12) at Function .executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) at node:internal/main/run_main_module:17:47*/

As you can see, when you need to do exception handling for a method, simply pass in the method as an argument. But the above example is a little different from the logic of the actual business development. In the actual business, we often encounter nested calls to methods, so let's try it:

Const f1 = () = > {console.log ('[F1]') f2 ();} const f2 = () = > {console.log ('[f2]') f3 ();} const f3 = () = > {console.log ('[f3]') throw new Error ('[f3 error!]')} errorHandling (F1) / * output: [F1 running] [f2 running] [f3 running] Error: [f3 error!] At f3 (/ Users/wangpingan/leo/www/node/www/a.js:24:11) at f2 (/ Users/wangpingan/leo/www/node/www/a.js:19:5) at F1 (/ Users/wangpingan/leo/www/node/www/a.js:14:5) at errorHandling (/ Users/wangpingan/leo/www/node/www/a.js:4:39) at Object. (/ Users/wangpingan/leo/www/node/www/a.js:27:1) at Module._compile (node:internal/modules/cjs/loader:1095:14) at Object.Module._extensions..js (node:internal/modules/cjs/loader:1147:10) at Module.load (node:internal/modules/cjs/loader:975:32) at Function.Module._load (node:internal/modules/cjs/loader:822:12) at Function .executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) * /

There is no problem with this. The next step is to implement the corresponding exception handling in the catch branch of the errorHandling method. Let's take a look at how it is handled in the Vue3 source code.

Third, how to implement exception handling in Vue3

After understanding the above example, let's take a look at how exception handling is implemented in the Vue3 source code, which is also easy to implement.

1. Implement exception handling method

Two methods of handling global exceptions, callWithErrorHandling and callWithAsyncErrorHandling, are defined in the errorHandling.ts file. As the name implies, these two methods deal with:

CallWithErrorHandling: handling exceptions to synchronous methods

CallWithAsyncErrorHandling: handles exceptions to asynchronous methods.

The mode of use is as follows:

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

The code implementation is roughly as follows:

/ / packages/runtime-core/src/errorHandling.ts// handles exception export function callWithErrorHandling of synchronous methods (fn: Function, instance: ComponentInternalInstance | null, type: ErrorTypes, args?: unknown []) {let res try {res = args? Fn (. Args): fn () / / call the original method} catch (err) {handleError (err, instance, type)} return res} / / handle the exception export function callWithAsyncErrorHandling of the asynchronous method (fn: Function | Function [], instance: ComponentInternalInstance | null, type: ErrorTypes, args?: unknown []): any [] {/ / omit other codes const res = callWithErrorHandling (fn, instance, type) Args) if (res & & isPromise (res)) {res.catch (err = > {handleError (err, instance, type)})} / / omit other code}

The logic of the callWithErrorHandling method is relatively simple, and it is encapsulated by a simple try...catch. The callWithAsyncErrorHandling method, on the other hand, is more ingenious by passing the method that needs to be executed into the callWithErrorHandling method and processing the result through the .catch method.

two。 Handling exceptions

In the above code, when an error is reported, the exception is handled through handleError (). The implementation is roughly as follows:

/ / packages/runtime-core/src/errorHandling.ts// exception handling method export function handleError (err: unknown, instance: ComponentInternalInstance | null, type: ErrorTypes, throwInDev = true) {/ / other codes logError (err, type, contextVNode, throwInDev)} function logError (err: unknown, type: ErrorTypes, contextVNode: VNode | null, throwInDev = true) {/ / other codes console.error (err)}

After preserving the core processing logic, you can see that the processing here is also quite simple, and the error content is output directly through console.error (err).

3. Configure errorHandler custom exception handlers

When using Vue3, it is also supported to specify custom exception handlers to handle uncaught errors thrown during component rendering functions and listener execution. When this handler is called, you can get the error message and the corresponding application example. Documentation reference: the use of "errorHandler" is as follows, which is configured in the project main.js file:

/ / src/main.jsapp.config.errorHandler = (err, vm, info) = > {/ / handling error / / `info` is a Vue-specific error message, such as the lifecycle hook where the error is located}

So when was errorHandler () executed? If we continue to look at the contents of handleError () in the source code, we can see that:

/ / 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) {/ / omit other code / / read the errorHandler configuration item const appErrorHandler = instance.appContext.config.errorHandler if (appErrorHandler) {callWithErrorHandling (appErrorHandler, null, ErrorCodes.APP_ERROR_HANDLER, [err, exposedInstance, errorInfo]) return}} logError (err, type, contextVNode, throwInDev)}

Get the custom error handling function of the global configuration through instance.appContext.config.errorHandler, and execute it when it exists. Of course, this is also called through the callWithErrorHandling defined earlier.

4. Call the errorCaptured lifecycle hook

When using Vue3, you can also catch errors from descendant components through errorCaptured lifecycle hooks. As follows:

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

This hook receives three parameters: the error object, the component instance where the error occurred, and a string containing the error source information. This hook can return false to prevent the error from propagating upward. Interested students can view the specific error propagation rules through the documentation. Using the following method, the parent component listens for the onErrorCaptured life cycle (the sample code uses Vue3 setup syntax):

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

The subcomponents are as follows:

Send the message / / Message.vueconst sendMessage = () = > {throw new Error ('[test onErrorCaptured]')}

When the "send message" button is clicked, the console outputs an error:

[errorCaptured] Error: [test onErrorCaptured] at Proxy.sendMessage (Message.vue:36:15) at _ createElementVNode.onClick._cache.._cache. (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: please, … } native event handler

You can see that the onErrorCaptured lifecycle hook executes normally and outputs the exception within the subcomponent Message.vue.

So how does this happen? Or look at the handleError () method in errorHandling.ts:

/ / 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 / / ① fetch the errorCaptured lifecycle method of the component configuration if (errorCapturedHooks) {/ / ② loop executes each Hook for in the errorCaptured (let I = 0; I < errorCapturedHooks.length) ) {if (errorCapturedHooks [I] (err, exposedInstance, errorInfo) = = false) {return} cur = cur.parent} / / omit other code} logError (err, type, contextVNode, throwInDev)}

Here, we will first get instance.parent as the currently processed component instance for recursion. Each time, the array of errorCaptured lifecycle methods configured by the component will be fetched and each hook will be called iteratively, then the parent component of the current component will be taken as a parameter, and finally the recursive call will continue.

5. Implement error codes and error messages

Vue3 also defines error codes and error messages for exceptions, and there are different error codes and error messages for different error situations, so that we can easily locate where the exception occurs. The error code and error message are as follows:

/ / packages/runtime-core/src/errorHandling.tsexport const enum ErrorCodes {SETUP_FUNCTION, RENDER_FUNCTION, WATCH_GETTER, WATCH_CALLBACK, / /... Omit other} export const ErrorTypeStrings: Record = {/ / omit other [LifecycleHooks.RENDER_TRACKED]: 'renderTracked hook', [LifecycleHooks.RENDER_TRIGGERED]:' renderTriggered hook', [ErrorCodes.SETUP_FUNCTION]: 'setup function', [ErrorCodes.RENDER_FUNCTION]:' render function', / / omit other [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'}

When different error conditions, get the ErrorTypeStrings error message according to the error code ErrorCodes to prompt:

/ / 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} `: ``}`) / / omit other} else {console.error (err)} 6. Implement Tree Shaking

For an introduction to Vue3's implementation of Tree Shaking, you can take a look at the efficient implementation framework I wrote earlier and the slimming of the JS library. Among them, the logError method is used:

/ / packages/runtime-core/src/errorHandling.tsfunction logError (err: unknown, type: ErrorTypes, contextVNode: VNode | null, throwInDev = true) {if (_ _ DEV__) {/ / omit other} else {console.error (err)}}

When compiled into the production environment, the code of the _ _ DEV__ branch is not packaged to optimize the size of the package.

At this point, I believe you have a deeper understanding of "how to handle global exceptions in Vue3". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report