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 use Proxy to handle exceptions more elegantly

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

Share

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

This article is about how to use Proxy to handle exceptions more elegantly. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

The code will not all run as expected, there may be unexpected circumstances, in order to ensure the robustness of the program, exception handling should be carried out.

For example, all methods of an object should do exception handling, but it would be too troublesome to add try catch to each method:

Const obj = {aaa () {try {/ aaa} catch (e) {/ / xxxx}}, bbb () {try {/ / bbb} catch (e) {/ / xxxx}} Ccc () {try {/ / ccc} catch (e) {/ / xxxx}

Is there a way to handle exceptions on all methods without having to repeat them so many times?

Yes, it is the agent mode.

The proxy mode is to provide a method with the same name as the target object by wrapping the target object, and the final function is to call the method of the target object, but some additional responsibilities, such as logs, permissions, etc., can be added to the target object transparently.

For example, the high-level component in React is the implementation of the proxy pattern, which can transparently extend the function of the packaged component.

Obviously, the exception handling here can also be done as a proxy. But you don't have to implement it entirely yourself. ES6 provides Proxy, which you can implement based on it.

Define the createProxy method to implement the proxy, create a Proxy object, wrap the target object target, and define the processing of get and set:

Function createProxy (target) {const proxy = createExceptionProxy (); return new Proxy (target, {get: proxy, set: proxy});} function createExceptionProxy () {return (target, prop) = > {if (! (prop in target)) {return;} if (typeof target [prop] = 'function') {return createExceptionZone (target, prop) } return target [prop];}}

If target does not contain prop, empty is returned, otherwise the corresponding property value target [prop] is returned.

If the property value is a function, do a wrapper:

Function createExceptionZone (target, prop) {return (... args) = > {let result; ExceptionsZone.run () = > {result = target [prop] (.. ARGs);}); return result;};}

The final functional implementation is to call target, pass in parameters, and return the result of the call as the result of the proxy method.

The purpose of wrapping this layer is to do exception handling, which is what ExceptionsZone.run does:

Class ExceptionsZone {static exceptionHandler = new ExceptionHandler (); static run (callback) {try {callback ();} catch (e) {this.exceptionHandler.handle (e);}

Call the target method and do try catch. When an exception occurs, use ExceptionHandler to handle it.

For the exception handling here, let's simply print the log:

Class ExceptionHandler {handle (exception) {console.log ('record error:', exception.message, exception.stack);}}

This achieves the goal of adding exception handling to all methods of the target object.

Test:

Const obj = {name: 'guang', say () {console.log (' Hi, I\'m'+ this.name);}, coding () {/ / xxx throw new Error ('bug');} coding2 () {/ / xxx throw new Error (' bug2');}} const proxy = createProxy (obj); proxy.say (); proxy.coding ()

The coding and coding2 methods here all throw an exception, but no exception handling is done. We use the proxy to add:

We successfully added exception handling to object methods through proxy mode!

But now there is still a problem. For example, I can't change the coding method to async:

What are we going to do? Can we uniformly act as proxies for asynchronous and synchronous methods?

There is no way, because it is impossible to tell whether a method is synchronous or asynchronous, and the two methods are called differently, but we can provide a separate runner method to run the asynchronous logic:

Class ExceptionsZone {static exceptionHandler = new ExceptionHandler (); static async asyncRun (callback) {try {await callback ();} catch (e) {this.exceptionHandler.handle (e);}

Then run it like this:

(async function () {await ExceptionsZone.asyncRun (proxy.coding2);}) ()

This allows you to handle exceptions in asynchronous logic:

We add exception handling to all synchronous methods of the object through proxy, and then provide runner functions that run asynchronous methods to handle asynchronous exceptions. Combined with these two ways, we elegantly add exception handling to all methods of the target object.

Maybe you will say, agent is agent, why do you define so many class?

Because this logic is extracted from the Nest.js source code, this is how the source code adds exception handling to objects:

Asynchronous logic also provides a separate way to run:

I thought this transparent way of adding exception handling to objects was elegant, so I pulled it out of the Nest.js source code.

The complete code is as follows:

Function createProxy (target) {const proxy = createExceptionProxy (); return new Proxy (target, {get: proxy, set: proxy});} function createExceptionProxy () {return (receiver, prop) = > {if (! (prop in receiver)) {return;} if (typeof receiver [prop] = 'function') {return createExceptionZone (receiver, prop) } return receiver [prop];}} function createExceptionZone (receiver, prop) {return (... args) = > {let result; ExceptionsZone.run () = > {result = receiver [prop] (.args);}); return result;};} class ExceptionHandler {handle (exception) {console.log ('record error:', exception.message, exception.stack) }} class ExceptionsZone {static exceptionHandler = new ExceptionHandler (); static run (callback) {try {callback ();} catch (e) {this.exceptionHandler.handle (e);}} static async asyncRun (callback) {try {await callback ();} catch (e) {this.exceptionHandler.handle (e) } const obj = {name: 'guang', say () {console.log (' Hi, I\'m'+ this.name);}, coding () {/ / xxx throw new Error ('bug');}, async coding2 () {/ / xxx throw new Error (' bug2');}} const proxy = createProxy (obj); proxy.say () Proxy.coding (); (async function () {await ExceptionsZone.asyncRun (proxy.coding2);}) (); Thank you for reading! This is the end of the article on "how to handle exceptions more elegantly with Proxy". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!

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