Skip to content

Commit 0ad7b1a

Browse files
committed
feat(errors): expose isRouterError
1 parent 49b3a76 commit 0ad7b1a

File tree

7 files changed

+67
-56
lines changed

7 files changed

+67
-56
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/history/base.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { _Vue } from '../install'
44
import type Router from '../index'
55
import { inBrowser } from '../util/dom'
66
import { runQueue } from '../util/async'
7-
import { warn, isError, isRouterError } from '../util/warn'
7+
import { warn } from '../util/warn'
88
import { START, isSameRoute } from '../util/route'
99
import {
1010
flatten,
@@ -15,7 +15,9 @@ import {
1515
createNavigationDuplicatedError,
1616
createNavigationCancelledError,
1717
createNavigationRedirectedError,
18-
createNavigationAbortedError
18+
createNavigationAbortedError,
19+
isError,
20+
isRouterError
1921
} from '../util/errors'
2022

2123
export class History {

src/index.js

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

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

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

3537
constructor (options: RouterOptions = {}) {
3638
this.app = null
@@ -42,7 +44,8 @@ export default class VueRouter {
4244
this.matcher = createMatcher(options.routes || [], this)
4345

4446
let mode = options.mode || 'hash'
45-
this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false
47+
this.fallback =
48+
mode === 'history' && !supportsPushState && options.fallback !== false
4649
if (this.fallback) {
4750
mode = 'hash'
4851
}
@@ -68,11 +71,7 @@ export default class VueRouter {
6871
}
6972
}
7073

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

@@ -81,11 +80,12 @@ export default class VueRouter {
8180
}
8281

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

9090
this.apps.push(app)
9191

@@ -120,11 +120,15 @@ export default class VueRouter {
120120
const setupListeners = () => {
121121
history.setupListeners()
122122
}
123-
history.transitionTo(history.getCurrentLocation(), setupListeners, setupListeners)
123+
history.transitionTo(
124+
history.getCurrentLocation(),
125+
setupListeners,
126+
setupListeners
127+
)
124128
}
125129

126130
history.listen(route => {
127-
this.apps.forEach((app) => {
131+
this.apps.forEach(app => {
128132
app._route = route
129133
})
130134
})
@@ -193,11 +197,14 @@ export default class VueRouter {
193197
if (!route) {
194198
return []
195199
}
196-
return [].concat.apply([], route.matched.map(m => {
197-
return Object.keys(m.components).map(key => {
198-
return m.components[key]
200+
return [].concat.apply(
201+
[],
202+
route.matched.map(m => {
203+
return Object.keys(m.components).map(key => {
204+
return m.components[key]
205+
})
199206
})
200-
}))
207+
)
201208
}
202209

203210
resolve (
@@ -213,12 +220,7 @@ export default class VueRouter {
213220
resolved: Route
214221
} {
215222
current = current || this.history.current
216-
const location = normalizeLocation(
217-
to,
218-
current,
219-
append,
220-
this
221-
)
223+
const location = normalizeLocation(to, current, append, this)
222224
const route = this.match(location, current)
223225
const fullPath = route.redirectedFrom || route.fullPath
224226
const base = this.history.base
@@ -256,6 +258,8 @@ function createHref (base: string, fullPath: string, mode) {
256258

257259
VueRouter.install = install
258260
VueRouter.version = '__VERSION__'
261+
VueRouter.isRouterError = isRouterError
262+
VueRouter.NavigationFailureType = NavigationFailureType
259263

260264
if (inBrowser && window.Vue) {
261265
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)