1
1
/**
2
2
* @coreapi
3
3
* @module transition
4
- */ /** for typedoc */
5
- import { TransitionHookOptions , HookResult } from "./interface" ;
6
- import { defaults , noop , identity } from "../common/common" ;
7
- import { fnToString , maxLength } from "../common/strings" ;
8
- import { isPromise } from "../common/predicates" ;
9
- import { val , is , parse } from "../common/hof" ;
10
- import { trace } from "../common/trace" ;
11
- import { services } from "../common/coreservices" ;
12
-
13
- import { Rejection } from "./rejectFactory" ;
14
- import { TargetState } from "../state/targetState" ;
15
- import { Transition } from "./transition" ;
16
- import { State } from "../state/stateObject" ;
17
- import { TransitionEventType } from "./transitionEventType" ;
18
- import { StateService } from "../state/stateService" ; // has or is using
19
- import { RegisteredHook } from "./hookRegistry" ; // has or is using
4
+ */
5
+ /** for typedoc */
6
+ import { TransitionHookOptions , HookResult } from './interface' ;
7
+ import { defaults , noop , silentRejection } from '../common/common' ;
8
+ import { fnToString , maxLength } from '../common/strings' ;
9
+ import { isPromise } from '../common/predicates' ;
10
+ import { is , parse } from '../common/hof' ;
11
+ import { trace } from '../common/trace' ;
12
+ import { services } from '../common/coreservices' ;
13
+ import { Rejection } from './rejectFactory' ;
14
+ import { TargetState } from '../state/targetState' ;
15
+ import { Transition } from './transition' ;
16
+ import { State } from '../state/stateObject' ;
17
+ import { TransitionEventType } from './transitionEventType' ;
18
+ import { RegisteredHook } from './hookRegistry' ; // has or is using
20
19
21
20
let defaultOptions : TransitionHookOptions = {
22
21
current : noop ,
@@ -33,35 +32,52 @@ export type ErrorHandler = (error) => Promise<any>;
33
32
34
33
/** @hidden */
35
34
export class TransitionHook {
35
+ type : TransitionEventType ;
36
36
constructor ( private transition : Transition ,
37
37
private stateContext : State ,
38
38
private registeredHook : RegisteredHook ,
39
39
private options : TransitionHookOptions ) {
40
40
this . options = defaults ( options , defaultOptions ) ;
41
+ this . type = registeredHook . eventType ;
41
42
}
42
43
43
- stateService = ( ) => this . transition . router . stateService ;
44
+ /**
45
+ * These GetResultHandler(s) are used by [[invokeHook]] below
46
+ * Each HookType chooses a GetResultHandler (See: [[TransitionService._defineCoreEvents]])
47
+ */
48
+ static HANDLE_RESULT : GetResultHandler = ( hook : TransitionHook ) => ( result : HookResult ) =>
49
+ hook . handleHookResult ( result ) ;
44
50
45
- static HANDLE_RESULT : GetResultHandler = ( hook : TransitionHook ) =>
46
- ( result : HookResult ) =>
47
- hook . handleHookResult ( result ) ;
51
+ /**
52
+ * If the result is a promise rejection, log it.
53
+ * Otherwise, ignore the result.
54
+ */
55
+ static LOG_REJECTED_RESULT : GetResultHandler = ( hook : TransitionHook ) => ( result : HookResult ) => {
56
+ isPromise ( result ) && result . catch ( err =>
57
+ hook . logError ( Rejection . normalize ( err ) ) ) ;
58
+ return undefined ;
59
+ } ;
48
60
49
- static IGNORE_RESULT : GetResultHandler = ( hook : TransitionHook ) =>
50
- ( result : HookResult ) => undefined ;
61
+ /**
62
+ * These GetErrorHandler(s) are used by [[invokeHook]] below
63
+ * Each HookType chooses a GetErrorHandler (See: [[TransitionService._defineCoreEvents]])
64
+ */
65
+ static LOG_ERROR : GetErrorHandler = ( hook : TransitionHook ) => ( error ) =>
66
+ hook . logError ( error ) ;
51
67
52
- static LOG_ERROR : GetErrorHandler = ( hook : TransitionHook ) =>
53
- ( error ) =>
54
- ( hook . stateService ( ) . defaultErrorHandler ( ) ( error ) , undefined ) ;
68
+ static REJECT_ERROR : GetErrorHandler = ( hook : TransitionHook ) => ( error ) =>
69
+ silentRejection ( error ) ;
55
70
56
- static REJECT_ERROR : GetErrorHandler = ( hook : TransitionHook ) =>
57
- ( error ) =>
58
- Rejection . errored ( error ) . toPromise ( ) ;
71
+ static THROW_ERROR : GetErrorHandler = ( hook : TransitionHook ) => ( error ) => {
72
+ throw error ;
73
+ } ;
59
74
60
- static THROW_ERROR : GetErrorHandler = ( hook : TransitionHook ) =>
61
- undefined ;
75
+ private isSuperseded = ( ) =>
76
+ ! this . type . synchronous && this . options . current ( ) !== this . options . transition ;
62
77
63
- private rejectIfSuperseded = ( ) =>
64
- this . registeredHook . eventType . rejectIfSuperseded && this . options . current ( ) !== this . options . transition ;
78
+ logError ( err ) : any {
79
+ this . transition . router . stateService . defaultErrorHandler ( ) ( err ) ;
80
+ }
65
81
66
82
invokeHook ( ) : Promise < HookResult > {
67
83
let hook = this . registeredHook ;
@@ -71,30 +87,36 @@ export class TransitionHook {
71
87
trace . traceHookInvocation ( this , this . transition , options ) ;
72
88
73
89
// A new transition started before this hook (from a previous transition) could be run.
74
- if ( this . rejectIfSuperseded ( ) ) {
90
+ if ( this . isSuperseded ( ) ) {
75
91
return Rejection . superseded ( options . current ( ) ) . toPromise ( ) ;
76
92
}
77
93
78
- let cb = hook . callback ;
79
- let bind = this . options . bind ;
80
- let trans = this . transition ;
81
- let state = this . stateContext ;
94
+ const invokeCallback = ( ) =>
95
+ hook . callback . call ( this . options . bind , this . transition , this . stateContext ) ;
82
96
83
- let errorHandler = hook . eventType . getErrorHandler ( this ) ;
84
- let resultHandler = hook . eventType . getResultHandler ( this ) ;
85
- resultHandler = resultHandler || identity ;
97
+ const normalizeErr = err =>
98
+ Rejection . normalize ( err ) . toPromise ( ) ;
86
99
87
- if ( ! errorHandler ) {
88
- return resultHandler ( cb . call ( bind , trans , state ) ) ;
89
- }
100
+ const handleError = err =>
101
+ hook . eventType . getErrorHandler ( this ) ( err ) ;
102
+
103
+ const handleResult = result =>
104
+ hook . eventType . getResultHandler ( this ) ( result ) ;
90
105
91
- try {
92
- return resultHandler ( cb . call ( bind , trans , state ) ) ;
93
- } catch ( error ) {
94
- return errorHandler ( error ) ;
106
+ if ( this . type . synchronous ) {
107
+ try {
108
+ return handleResult ( invokeCallback ( ) ) ;
109
+ } catch ( err ) {
110
+ return handleError ( Rejection . normalize ( err ) ) ;
111
+ }
95
112
}
113
+
114
+ return services . $q . when ( )
115
+ . then ( invokeCallback )
116
+ . catch ( normalizeErr )
117
+ . then ( handleResult , handleError ) ;
96
118
}
97
-
119
+
98
120
/**
99
121
* This method handles the return value of a Transition Hook.
100
122
*
@@ -107,15 +129,15 @@ export class TransitionHook {
107
129
handleHookResult ( result : HookResult ) : Promise < HookResult > {
108
130
// This transition is no longer current.
109
131
// Another transition started while this hook was still running.
110
- if ( this . rejectIfSuperseded ( ) ) {
132
+ if ( this . isSuperseded ( ) ) {
111
133
// Abort this transition
112
134
return Rejection . superseded ( this . options . current ( ) ) . toPromise ( ) ;
113
135
}
114
136
115
137
// Hook returned a promise
116
138
if ( isPromise ( result ) ) {
117
- // Wait for the promise, then reprocess the settled promise value
118
- return result . then ( this . handleHookResult . bind ( this ) ) ;
139
+ // Wait for the promise, then reprocess with the resulting value
140
+ return result . then ( val => this . handleHookResult ( val ) ) ;
119
141
}
120
142
121
143
trace . traceHookResult ( result , this . transition , this . options ) ;
0 commit comments