Skip to content

Commit 8d92dc0

Browse files
committed
feat(errors): expose isRouterError
1 parent 49d3d51 commit 8d92dc0

File tree

6 files changed

+63
-54
lines changed

6 files changed

+63
-54
lines changed

docs/guide/advanced/navigation-failures.md

+10-6
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,26 @@ When using a regular `router-link`, **none of these failures will log an error**
1010

1111
## Detecting Navigation Failures
1212

13-
_Navigation Failures_ are `Error` instances with a few extra properties. Among them, you can find a `type` property. This will allow you to check the type of the navigation failure:
13+
_Navigation Failures_ are `Error` instances with a few extra properties. To check if an error comes from the Router, use the `isRouterError` function:
1414

1515
```js
16-
import { NavigationFailureType } from 'vue-router'
16+
import { NavigationFailureType, isRouterError } from 'vue-router'
1717

18-
// trying to access an admin-only route
18+
// trying to access the admin page
1919
router.push('/admin').catch(failure => {
2020
if (failure) {
21-
if (failure.type === NavigationFailureType.redirected) {
21+
if (isRouterError(failure, NavigationFailureType.redirected)) {
2222
// show a small notification to the user
2323
showToast('Login in order to access the admin panel')
2424
}
2525
}
2626
})
2727
```
2828

29+
::: tip
30+
If you omit the second parameter: `isRouterError(failure)`, it will only check if the error comes from the Router.
31+
:::
32+
2933
## `NavigationFailureType`
3034

3135
`NavigationFailureType` exposes the following properties to differentiate _Navigation Failures_:
@@ -40,10 +44,10 @@ router.push('/admin').catch(failure => {
4044
Apart from exposing a `type` property, all navigation failures expose `to` and `from` properties to reflect the current location as well as the target location for the navigation that failed:
4145

4246
```js
43-
// given we are at `/`
47+
// trying to access the admin page
4448
router.push('/admin').catch(failure => {
4549
if (failure) {
46-
if (failure.type === NavigationFailureType.redirected) {
50+
if (isRouterError(failure, NavigationFailureType.redirected)) {
4751
failure.to.path // '/admin'
4852
failure.from.path // '/'
4953
}

src/history/abstract.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
import type Router from '../index'
44
import { History } from './base'
5-
import { isRouterError } from '../util/warn'
6-
import { NavigationFailureType } from '../util/errors'
5+
import { NavigationFailureType, isRouterError } from '../util/errors'
76

87
export class AbstractHistory extends History {
98
index: number

src/index.js

+42-38
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,24 @@ import { AbstractHistory } from './history/abstract'
1616

1717
import type { Matcher } from './create-matcher'
1818

19+
import { isRouterError, NavigationFailureType } from './util/errors'
20+
1921
export default class VueRouter {
20-
static install: () => void;
21-
static version: string;
22-
23-
app: any;
24-
apps: Array<any>;
25-
ready: boolean;
26-
readyCbs: Array<Function>;
27-
options: RouterOptions;
28-
mode: string;
29-
history: HashHistory | HTML5History | AbstractHistory;
30-
matcher: Matcher;
31-
fallback: boolean;
32-
beforeHooks: Array<?NavigationGuard>;
33-
resolveHooks: Array<?NavigationGuard>;
34-
afterHooks: Array<?AfterNavigationHook>;
22+
static install: () => void
23+
static version: string
24+
25+
app: any
26+
apps: Array<any>
27+
ready: boolean
28+
readyCbs: Array<Function>
29+
options: RouterOptions
30+
mode: string
31+
history: HashHistory | HTML5History | AbstractHistory
32+
matcher: Matcher
33+
fallback: boolean
34+
beforeHooks: Array<?NavigationGuard>
35+
resolveHooks: Array<?NavigationGuard>
36+
afterHooks: Array<?AfterNavigationHook>
3537

3638
constructor (options: RouterOptions = {}) {
3739
this.app = null
@@ -43,7 +45,8 @@ export default class VueRouter {
4345
this.matcher = createMatcher(options.routes || [], this)
4446

4547
let mode = options.mode || 'hash'
46-
this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false
48+
this.fallback =
49+
mode === 'history' && !supportsPushState && options.fallback !== false
4750
if (this.fallback) {
4851
mode = 'hash'
4952
}
@@ -69,11 +72,7 @@ export default class VueRouter {
6972
}
7073
}
7174

72-
match (
73-
raw: RawLocation,
74-
current?: Route,
75-
redirectedFrom?: Location
76-
): Route {
75+
match (raw: RawLocation, current?: Route, redirectedFrom?: Location): Route {
7776
return this.matcher.match(raw, current, redirectedFrom)
7877
}
7978

@@ -82,11 +81,12 @@ export default class VueRouter {
8281
}
8382

8483
init (app: any /* Vue component instance */) {
85-
process.env.NODE_ENV !== 'production' && assert(
86-
install.installed,
87-
`not installed. Make sure to call \`Vue.use(VueRouter)\` ` +
88-
`before creating root instance.`
89-
)
84+
process.env.NODE_ENV !== 'production' &&
85+
assert(
86+
install.installed,
87+
`not installed. Make sure to call \`Vue.use(VueRouter)\` ` +
88+
`before creating root instance.`
89+
)
9090

9191
this.apps.push(app)
9292

@@ -131,11 +131,15 @@ export default class VueRouter {
131131
history.setupListeners()
132132
handleInitialScroll(routeOrError)
133133
}
134-
history.transitionTo(history.getCurrentLocation(), setupListeners, setupListeners)
134+
history.transitionTo(
135+
history.getCurrentLocation(),
136+
setupListeners,
137+
setupListeners
138+
)
135139
}
136140

137141
history.listen(route => {
138-
this.apps.forEach((app) => {
142+
this.apps.forEach(app => {
139143
app._route = route
140144
})
141145
})
@@ -204,11 +208,14 @@ export default class VueRouter {
204208
if (!route) {
205209
return []
206210
}
207-
return [].concat.apply([], route.matched.map(m => {
208-
return Object.keys(m.components).map(key => {
209-
return m.components[key]
211+
return [].concat.apply(
212+
[],
213+
route.matched.map(m => {
214+
return Object.keys(m.components).map(key => {
215+
return m.components[key]
216+
})
210217
})
211-
}))
218+
)
212219
}
213220

214221
resolve (
@@ -224,12 +231,7 @@ export default class VueRouter {
224231
resolved: Route
225232
} {
226233
current = current || this.history.current
227-
const location = normalizeLocation(
228-
to,
229-
current,
230-
append,
231-
this
232-
)
234+
const location = normalizeLocation(to, current, append, this)
233235
const route = this.match(location, current)
234236
const fullPath = route.redirectedFrom || route.fullPath
235237
const base = this.history.base
@@ -267,6 +269,8 @@ function createHref (base: string, fullPath: string, mode) {
267269

268270
VueRouter.install = install
269271
VueRouter.version = '__VERSION__'
272+
VueRouter.isRouterError = isRouterError
273+
VueRouter.NavigationFailureType = NavigationFailureType
270274

271275
if (inBrowser && window.Vue) {
272276
window.Vue.use(VueRouter)

src/util/errors.js

+8
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,11 @@ function stringifyRoute (to) {
7171
})
7272
return JSON.stringify(location, null, 2)
7373
}
74+
75+
export function isError (err) {
76+
return Object.prototype.toString.call(err).indexOf('Error') > -1
77+
}
78+
79+
export function isRouterError (err, errorType) {
80+
return isError(err) && err._isRouter && (errorType == null || err.type === errorType)
81+
}

src/util/resolve-components.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/* @flow */
22

33
import { _Vue } from '../install'
4-
import { warn, isError } from './warn'
4+
import { warn } from './warn'
5+
import { isError } from '../util/errors'
56

67
export function resolveAsyncComponents (matched: Array<RouteRecord>): Function {
78
return (to, from, next) => {

src/util/warn.js

-7
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,3 @@ export function warn (condition: any, message: string) {
1212
}
1313
}
1414

15-
export function isError (err: any): boolean {
16-
return Object.prototype.toString.call(err).indexOf('Error') > -1
17-
}
18-
19-
export function isRouterError (err: any, errorType: ?string): boolean {
20-
return isError(err) && err._isRouter && (errorType == null || err.type === errorType)
21-
}

0 commit comments

Comments
 (0)