-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Closes: #18
- Loading branch information
Showing
3 changed files
with
99 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Interceptors | ||
|
||
An interceptor is a class annotated with the @@Interceptor@@ decorator. Interceptors should implement the @@InterceptorMethods@@ interface. | ||
|
||
Interceptors have a set of useful capabilities which are inspired by the [Aspect Oriented Programming](https://en.wikipedia.org/wiki/Aspect-oriented_programming) (AOP) technique. | ||
|
||
Creating and consuming an interceptor is a two-step process: | ||
|
||
1. Create and annotate the interceptor class that will intercept calls to service methods | ||
2. Decide which methods will be **intercepted** by which **interceptor** | ||
|
||
They make it possible to: | ||
|
||
- bind extra logic before/after method execution | ||
- transform the result returned from a function | ||
- transform the exception thrown from a function | ||
- extend the basic function's behavior | ||
- completely override a function depending on specific conditions | ||
|
||
## Decorators | ||
|
||
<ApiList query="module == '@tsed/di' && symbolType === 'decorator'" /> | ||
|
||
## Interceptor class | ||
|
||
To create an interceptor class you need to implement the @@InterceptorMethods@@ interface and implement the | ||
`intercept(context: InterceptorContext<any>, next?: InterceptorNext)` method, and use the `@Interceptor()` annotation to register your interceptor class. | ||
|
||
Inside your `src/interceptors/MyInterceptor.ts` file, create the following simple interceptor. | ||
|
||
<<< @/docs/snippets/interceptors/interceptor-example.ts | ||
|
||
## Use the interceptor | ||
|
||
Now that your interceptor logic is in place, you can use it in any other service. You need to use the `@Intercept(InterceptorClass, opts)` annotation to register which interceptor should be used for the specific method you want to intercept. | ||
An example service in `src/services/MyService.ts`: | ||
|
||
<<< @/docs/snippets/interceptors/interceptor-usage.ts | ||
|
||
If the service method is executed like `myServiceInstance.mySimpleMethod()` we will get the following output: | ||
|
||
```bash | ||
the method mySimpleMethod will be executed with args and static data simple data | ||
the simple method is executed | ||
the method was executed, and returned undefined | ||
``` | ||
|
||
## Catch error with Interceptor | ||
|
||
You can also catch errors with an interceptor. | ||
To do this, you need to implement the `intercept` method in your interceptor class: | ||
|
||
<<< @/docs/snippets/interceptors/interceptor-catch-error.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import {InterceptorMethods, InterceptorContext, InterceptorNext, Interceptor} from "@tsed/di"; | ||
|
||
@Interceptor() | ||
export class MyInterceptor implements InterceptorMethods { | ||
/** | ||
* ctx: The context that holds the dynamic data related to the method execution and the proceed method | ||
* to proceed with the original method execution | ||
* | ||
* opts: Static params that can be provided when the interceptor is attached to a specific method | ||
*/ | ||
async intercept(context: InterceptorContext<any>, next: InterceptorNext) { | ||
console.log(`the method ${context.propertyKey} will be executed with args ${context.args} and static data ${context.options}`); | ||
// let the original method by calling next function | ||
const result = await next(); | ||
|
||
console.log(`the method was executed, and returned ${result}`); | ||
|
||
// must return the returned value back to the caller | ||
return result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import {Intercept, Injectable} from "@tsed/di"; | ||
import {MyInterceptor} from "../interceptors/MyInterceptor"; | ||
|
||
@Injectable() | ||
export class MyService { | ||
// MyInterceptor is going to be used to intercept this method whenever called | ||
// 'simple data' is static data that will be passed as second arg to the interceptor.intercept method | ||
@Intercept(MyInterceptor, "simple data") | ||
mySimpleMethod() { | ||
console.log("the simple method is executed"); | ||
} | ||
} | ||
|
||
// on class | ||
@Injectable() | ||
@Intercept(MyInterceptor, "simple data") | ||
export class MyService2 { | ||
mySimpleMethod1() { | ||
console.log("the simple method is executed"); | ||
} | ||
|
||
mySimpleMethod2() { | ||
console.log("the simple method is executed"); | ||
} | ||
} |