1
1
/** @coreapi @module transition */ /** for typedoc */
2
2
import { TransitionHookOptions , IEventHook , HookResult } from "./interface" ;
3
- import { defaults , noop } from "../common/common" ;
3
+ import { defaults , noop , identity } from "../common/common" ;
4
4
import { fnToString , maxLength } from "../common/strings" ;
5
5
import { isPromise } from "../common/predicates" ;
6
- import { val , is , parse } from "../common/hof" ;
6
+ import { val , is , parse } from "../common/hof" ;
7
7
import { trace } from "../common/trace" ;
8
8
import { services } from "../common/coreservices" ;
9
9
10
10
import { Rejection } from "./rejectFactory" ;
11
11
import { TargetState } from "../state/targetState" ;
12
12
import { Transition } from "./transition" ;
13
13
import { State } from "../state/stateObject" ;
14
+ import { StateService } from "../state/stateService" ; // has or is using
15
+ import { TransitionHookType } from "./transitionHookType" ; // has or is using
14
16
15
17
let defaultOptions : TransitionHookOptions = {
16
18
async : true ,
@@ -21,30 +23,77 @@ let defaultOptions: TransitionHookOptions = {
21
23
bind : null
22
24
} ;
23
25
26
+ export type GetResultHandler = ( hook : TransitionHook ) => ResultHandler ;
27
+ export type GetErrorHandler = ( hook : TransitionHook ) => ErrorHandler ;
28
+
29
+ export type ResultHandler = ( result : HookResult ) => Promise < HookResult > ;
30
+ export type ErrorHandler = ( error ) => Promise < any > ;
31
+
24
32
/** @hidden */
25
33
export class TransitionHook {
26
34
constructor ( private transition : Transition ,
27
35
private stateContext : State ,
28
36
private eventHook : IEventHook ,
37
+ private hookType : TransitionHookType ,
29
38
private options : TransitionHookOptions ) {
30
39
this . options = defaults ( options , defaultOptions ) ;
31
40
}
32
41
33
- private isSuperseded = ( ) =>
34
- this . options . current ( ) !== this . options . transition ;
42
+ stateService = ( ) => this . transition . router . stateService ;
43
+
44
+ static HANDLE_RESULT : GetResultHandler = ( hook : TransitionHook ) =>
45
+ ( result : HookResult ) =>
46
+ hook . handleHookResult ( result ) ;
47
+
48
+ static IGNORE_RESULT : GetResultHandler = ( hook : TransitionHook ) =>
49
+ ( result : HookResult ) => undefined ;
50
+
51
+ static LOG_ERROR : GetErrorHandler = ( hook : TransitionHook ) =>
52
+ ( error ) =>
53
+ ( hook . stateService ( ) . defaultErrorHandler ( ) ( error ) , undefined ) ;
54
+
55
+ static REJECT_ERROR : GetErrorHandler = ( hook : TransitionHook ) =>
56
+ ( error ) =>
57
+ Rejection . errored ( error ) . toPromise ( ) ;
58
+
59
+ static THROW_ERROR : GetErrorHandler = ( hook : TransitionHook ) =>
60
+ undefined ;
61
+
62
+ private rejectForSuperseded = ( ) =>
63
+ this . hookType . rejectIfSuperseded && this . options . current ( ) !== this . options . transition ;
35
64
36
65
invokeHook ( ) : Promise < HookResult > {
37
- let { options, eventHook } = this ;
66
+ if ( this . eventHook . _deregistered ) return ;
67
+
68
+ let options = this . options ;
38
69
trace . traceHookInvocation ( this , options ) ;
39
- if ( options . rejectIfSuperseded && this . isSuperseded ( ) ) {
70
+
71
+ if ( this . rejectForSuperseded ( ) ) {
40
72
return Rejection . superseded ( options . current ( ) ) . toPromise ( ) ;
41
73
}
42
74
43
- let synchronousHookResult = ! eventHook . _deregistered
44
- ? eventHook . callback . call ( options . bind , this . transition , this . stateContext )
45
- : undefined ;
75
+ let errorHandler = this . hookType . errorHandler ( this ) ;
76
+ let resultHandler = this . hookType . resultHandler ( this ) ;
46
77
47
- return this . handleHookResult ( synchronousHookResult ) ;
78
+ return this . _invokeCallback ( resultHandler , errorHandler ) ;
79
+ }
80
+
81
+ private _invokeCallback ( resultHandler : ResultHandler , errorHandler : ErrorHandler ) : Promise < HookResult > {
82
+ let cb = this . eventHook . callback ;
83
+ let bind = this . options . bind ;
84
+ let trans = this . transition ;
85
+ let state = this . stateContext ;
86
+ resultHandler = resultHandler || identity ;
87
+
88
+ if ( ! errorHandler ) {
89
+ return resultHandler ( cb . call ( bind , trans , state ) ) ;
90
+ }
91
+
92
+ try {
93
+ return resultHandler ( cb . call ( bind , trans , state ) ) ;
94
+ } catch ( error ) {
95
+ return errorHandler ( error ) ;
96
+ }
48
97
}
49
98
50
99
/**
@@ -56,10 +105,10 @@ export class TransitionHook {
56
105
* This also handles "transition superseded" -- when a new transition
57
106
* was started while the hook was still running
58
107
*/
59
- handleHookResult ( result : HookResult ) : Promise < any > {
108
+ handleHookResult ( result : HookResult ) : Promise < HookResult > {
60
109
// This transition is no longer current.
61
110
// Another transition started while this hook was still running.
62
- if ( this . isSuperseded ( ) ) {
111
+ if ( this . rejectForSuperseded ( ) ) {
63
112
// Abort this transition
64
113
return Rejection . superseded ( this . options . current ( ) ) . toPromise ( ) ;
65
114
}
@@ -98,14 +147,7 @@ export class TransitionHook {
98
147
* Run all TransitionHooks, ignoring their return value.
99
148
*/
100
149
static runAllHooks ( hooks : TransitionHook [ ] ) : void {
101
- hooks . forEach ( hook => {
102
- try {
103
- hook . invokeHook ( ) ;
104
- } catch ( exception ) {
105
- let errorHandler = hook . transition . router . stateService . defaultErrorHandler ( ) ;
106
- errorHandler ( exception ) ;
107
- }
108
- } ) ;
150
+ hooks . forEach ( hook => hook . invokeHook ( ) ) ;
109
151
}
110
152
111
153
/**
@@ -114,22 +156,18 @@ export class TransitionHook {
114
156
*
115
157
* Returns a promise chain composed of any promises returned from each hook.invokeStep() call
116
158
*/
117
- static runSynchronousHooks ( hooks : TransitionHook [ ] ) : Promise < any > {
159
+ static runOnBeforeHooks ( hooks : TransitionHook [ ] ) : Promise < any > {
118
160
let results : Promise < HookResult > [ ] = [ ] ;
119
161
120
162
for ( let hook of hooks ) {
121
- try {
122
- let hookResult = hook . invokeHook ( ) ;
123
-
124
- if ( Rejection . isTransitionRejectionPromise ( hookResult ) ) {
125
- // Break on first thrown error or false/TargetState
126
- return hookResult ;
127
- }
128
-
129
- results . push ( hookResult ) ;
130
- } catch ( exception ) {
131
- return Rejection . errored ( exception ) . toPromise ( ) ;
163
+ let hookResult = hook . invokeHook ( ) ;
164
+
165
+ if ( Rejection . isTransitionRejectionPromise ( hookResult ) ) {
166
+ // Break on first thrown error or false/TargetState
167
+ return hookResult ;
132
168
}
169
+
170
+ results . push ( hookResult ) ;
133
171
}
134
172
135
173
return results
0 commit comments