@@ -15,6 +15,8 @@ export class History {
15
15
cb: ( r : Route ) => void ;
16
16
ready: boolean ;
17
17
readyCbs: Array < Function > ;
18
+ readyErrorCbs: Array < Function > ;
19
+ errorCbs: Array < Function > ;
18
20
19
21
// implemented by sub-classes
20
22
+ go : ( n : number ) = > void ;
@@ -31,20 +33,29 @@ export class History {
31
33
this . pending = null
32
34
this . ready = false
33
35
this . readyCbs = [ ]
36
+ this . readyErrorCbs = [ ]
37
+ this . errorCbs = [ ]
34
38
}
35
39
36
40
listen ( cb : Function ) {
37
41
this . cb = cb
38
42
}
39
43
40
- onReady ( cb : Function ) {
44
+ onReady ( cb : Function , errorCb : ? Function ) {
41
45
if ( this . ready ) {
42
46
cb ( )
43
47
} else {
44
48
this . readyCbs . push ( cb )
49
+ if ( errorCb ) {
50
+ this . readyErrorCbs . push ( errorCb )
51
+ }
45
52
}
46
53
}
47
54
55
+ onError ( errorCb : Function ) {
56
+ this . errorCbs . push ( errorCb )
57
+ }
58
+
48
59
transitionTo ( location : RawLocation , onComplete ? : Function , onAbort ? : Function ) {
49
60
const route = this . router . match ( location , this . current )
50
61
this . confirmTransition ( route , ( ) => {
@@ -55,16 +66,27 @@ export class History {
55
66
// fire ready cbs once
56
67
if ( ! this . ready ) {
57
68
this . ready = true
58
- this . readyCbs . forEach ( cb => {
59
- cb ( route )
60
- } )
69
+ this . readyCbs . forEach ( cb => { cb ( route ) } )
61
70
}
62
- } , onAbort )
71
+ } , err => {
72
+ if ( onAbort ) {
73
+ onAbort ( err )
74
+ }
75
+ if ( err && ! this . ready ) {
76
+ this . ready = true
77
+ this . readyErrorCbs . forEach ( cb => { cb ( err ) } )
78
+ }
79
+ } )
63
80
}
64
81
65
82
confirmTransition ( route : Route , onComplete : Function , onAbort ? : Function ) {
66
83
const current = this . current
67
- const abort = ( ) => { onAbort && onAbort ( ) }
84
+ const abort = err => {
85
+ if ( err instanceof Error ) {
86
+ this . errorCbs . forEach ( cb => { cb ( err ) } )
87
+ }
88
+ onAbort && onAbort ( err )
89
+ }
68
90
if (
69
91
isSameRoute ( route , current ) &&
70
92
// in the case the route map has been dynamically appended to
@@ -98,20 +120,28 @@ export class History {
98
120
if ( this . pending !== route ) {
99
121
return abort ( )
100
122
}
101
- hook ( route , current , ( to : any ) => {
102
- if ( to === false ) {
103
- // next(false) -> abort navigation, ensure current URL
104
- this . ensureURL ( true )
105
- abort ( )
106
- } else if ( typeof to === 'string' || typeof to === 'object' ) {
107
- // next('/') or next({ path: '/' }) -> redirect
108
- ( typeof to === 'object' && to . replace ) ? this . replace ( to ) : this . push ( to )
109
- abort ( )
110
- } else {
111
- // confirm transition and pass on the value
112
- next ( to )
113
- }
114
- } )
123
+ try {
124
+ hook ( route , current , ( to : any ) => {
125
+ if ( to === false || to instanceof Error ) {
126
+ // next(false) -> abort navigation, ensure current URL
127
+ this . ensureURL ( true )
128
+ abort ( to )
129
+ } else if ( typeof to === 'string' || typeof to === 'object' ) {
130
+ // next('/') or next({ path: '/' }) -> redirect
131
+ abort ( )
132
+ if ( typeof to === 'object' && to . replace ) {
133
+ this . replace ( to )
134
+ } else {
135
+ this . push ( to )
136
+ }
137
+ } else {
138
+ // confirm transition and pass on the value
139
+ next ( to )
140
+ }
141
+ } )
142
+ } catch ( e ) {
143
+ abort ( e )
144
+ }
115
145
}
116
146
117
147
runQueue ( queue , iterator , ( ) => {
@@ -128,7 +158,7 @@ export class History {
128
158
onComplete ( route )
129
159
if ( this . router . app ) {
130
160
this . router . app . $nextTick ( ( ) => {
131
- postEnterCbs . forEach ( cb => cb ( ) )
161
+ postEnterCbs . forEach ( cb => { cb ( ) } )
132
162
} )
133
163
}
134
164
} )
@@ -279,7 +309,7 @@ function poll (
279
309
function resolveAsyncComponents ( matched : Array < RouteRecord > ) : Function {
280
310
let _next
281
311
let pending = 0
282
- let rejected = false
312
+ let error = null
283
313
284
314
flatMapComponents ( matched , ( def , _ , match , key ) => {
285
315
// if it's a function and doesn't have cid attached,
@@ -299,23 +329,31 @@ function resolveAsyncComponents (matched: Array<RouteRecord>): Function {
299
329
} )
300
330
301
331
const reject = once ( reason => {
302
- warn ( false , `Failed to resolve async component ${ key } : ${ reason } ` )
303
- if ( ! rejected ) {
304
- rejected = true
305
- if ( _next ) _next ( false )
332
+ const msg = `Failed to resolve async component ${ key } : ${ reason } `
333
+ process . env . NODE_ENV !== 'production' && warn ( false , msg )
334
+ if ( ! error ) {
335
+ error = reason instanceof Error
336
+ ? reason
337
+ : new Error ( msg )
338
+ if ( _next ) _next ( error )
306
339
}
307
340
} )
308
341
309
- const res = def ( resolve , reject )
342
+ let res
343
+ try {
344
+ res = def ( resolve , reject )
345
+ } catch ( e ) {
346
+ reject ( e )
347
+ }
310
348
if ( res && typeof res . then === 'function' ) {
311
349
res . then ( resolve , reject )
312
350
}
313
351
}
314
352
} )
315
353
316
354
return ( to , from , next ) = > {
317
- if ( rejected ) {
318
- next ( false )
355
+ if ( error ) {
356
+ next ( error )
319
357
} else if ( pending <= 0 ) {
320
358
next ( )
321
359
} else {
0 commit comments