123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- /* @flow */
- import { _Vue } from '../install'
- import { warn } from './warn'
- import { isError } from '../util/errors'
- export function resolveAsyncComponents (matched: Array<RouteRecord>): Function {
- return (to, from, next) => {
- let hasAsync = false
- let pending = 0
- let error = null
- flatMapComponents(matched, (def, _, match, key) => {
- // if it's a function and doesn't have cid attached,
- // assume it's an async component resolve function.
- // we are not using Vue's default async resolving mechanism because
- // we want to halt the navigation until the incoming component has been
- // resolved.
- if (typeof def === 'function' && def.cid === undefined) {
- hasAsync = true
- pending++
- const resolve = once(resolvedDef => {
- if (isESModule(resolvedDef)) {
- resolvedDef = resolvedDef.default
- }
- // save resolved on async factory in case it's used elsewhere
- def.resolved = typeof resolvedDef === 'function'
- ? resolvedDef
- : _Vue.extend(resolvedDef)
- match.components[key] = resolvedDef
- pending--
- if (pending <= 0) {
- next()
- }
- })
- const reject = once(reason => {
- const msg = `Failed to resolve async component ${key}: ${reason}`
- process.env.NODE_ENV !== 'production' && warn(false, msg)
- if (!error) {
- error = isError(reason)
- ? reason
- : new Error(msg)
- next(error)
- }
- })
- let res
- try {
- res = def(resolve, reject)
- } catch (e) {
- reject(e)
- }
- if (res) {
- if (typeof res.then === 'function') {
- res.then(resolve, reject)
- } else {
- // new syntax in Vue 2.3
- const comp = res.component
- if (comp && typeof comp.then === 'function') {
- comp.then(resolve, reject)
- }
- }
- }
- }
- })
- if (!hasAsync) next()
- }
- }
- export function flatMapComponents (
- matched: Array<RouteRecord>,
- fn: Function
- ): Array<?Function> {
- return flatten(matched.map(m => {
- return Object.keys(m.components).map(key => fn(
- m.components[key],
- m.instances[key],
- m, key
- ))
- }))
- }
- export function flatten (arr: Array<any>): Array<any> {
- return Array.prototype.concat.apply([], arr)
- }
- const hasSymbol =
- typeof Symbol === 'function' &&
- typeof Symbol.toStringTag === 'symbol'
- function isESModule (obj) {
- return obj.__esModule || (hasSymbol && obj[Symbol.toStringTag] === 'Module')
- }
- // in Webpack 2, require.ensure now also returns a Promise
- // so the resolve/reject functions may get called an extra time
- // if the user uses an arrow function shorthand that happens to
- // return that Promise.
- function once (fn) {
- let called = false
- return function (...args) {
- if (called) return
- called = true
- return fn.apply(this, args)
- }
- }
|