feat(asyncComponent): add onError option for defineAsyncComponent

BREAKING CHANGE: `retryWhen` and `maxRetries` options for
`defineAsyncComponent` has been replaced by the more flexible `onError`
option, per https://github.com/vuejs/rfcs/pull/148
This commit is contained in:
Evan You 2020-04-07 14:34:42 -04:00
parent f87d6b501e
commit e804463492
2 changed files with 38 additions and 14 deletions

View File

@ -488,7 +488,13 @@ describe('api: defineAsyncComponent', () => {
reject = _reject reject = _reject
}) })
}, },
retryWhen: error => error.message.match(/foo/) onError(error, retry, fail) {
if (error.message.match(/foo/)) {
retry()
} else {
fail()
}
}
}) })
const root = nodeOps.createElement('div') const root = nodeOps.createElement('div')
@ -526,7 +532,13 @@ describe('api: defineAsyncComponent', () => {
reject = _reject reject = _reject
}) })
}, },
retryWhen: error => error.message.match(/bar/) onError(error, retry, fail) {
if (error.message.match(/bar/)) {
retry()
} else {
fail()
}
}
}) })
const root = nodeOps.createElement('div') const root = nodeOps.createElement('div')
@ -549,7 +561,7 @@ describe('api: defineAsyncComponent', () => {
expect(serializeInner(root)).toBe('<!---->') expect(serializeInner(root)).toBe('<!---->')
}) })
test('retry (fail w/ maxRetries)', async () => { test('retry (fail w/ max retry attempts)', async () => {
let loaderCallCount = 0 let loaderCallCount = 0
let reject: (e: Error) => void let reject: (e: Error) => void
@ -560,8 +572,13 @@ describe('api: defineAsyncComponent', () => {
reject = _reject reject = _reject
}) })
}, },
retryWhen: error => error.message.match(/foo/), onError(error, retry, fail, attempts) {
maxRetries: 1 if (error.message.match(/foo/) && attempts <= 1) {
retry()
} else {
fail()
}
}
}) })
const root = nodeOps.createElement('div') const root = nodeOps.createElement('div')

View File

@ -5,7 +5,7 @@ import {
ComponentInternalInstance, ComponentInternalInstance,
isInSSRComponentSetup isInSSRComponentSetup
} from './component' } from './component'
import { isFunction, isObject, NO } from '@vue/shared' import { isFunction, isObject } from '@vue/shared'
import { ComponentPublicInstance } from './componentProxy' import { ComponentPublicInstance } from './componentProxy'
import { createVNode } from './vnode' import { createVNode } from './vnode'
import { defineComponent } from './apiDefineComponent' import { defineComponent } from './apiDefineComponent'
@ -27,9 +27,13 @@ export interface AsyncComponentOptions<T = any> {
errorComponent?: PublicAPIComponent errorComponent?: PublicAPIComponent
delay?: number delay?: number
timeout?: number timeout?: number
retryWhen?: (error: Error) => any
maxRetries?: number
suspensible?: boolean suspensible?: boolean
onError?: (
error: Error,
retry: () => void,
fail: () => void,
attempts: number
) => any
} }
export function defineAsyncComponent< export function defineAsyncComponent<
@ -45,16 +49,15 @@ export function defineAsyncComponent<
errorComponent: errorComponent, errorComponent: errorComponent,
delay = 200, delay = 200,
timeout, // undefined = never times out timeout, // undefined = never times out
retryWhen = NO, suspensible = true,
maxRetries = 3, onError: userOnError
suspensible = true
} = source } = source
let pendingRequest: Promise<Component> | null = null let pendingRequest: Promise<Component> | null = null
let resolvedComp: Component | undefined let resolvedComp: Component | undefined
let retries = 0 let retries = 0
const retry = (error?: unknown) => { const retry = () => {
retries++ retries++
pendingRequest = null pendingRequest = null
return load() return load()
@ -67,8 +70,12 @@ export function defineAsyncComponent<
(thisRequest = pendingRequest = loader() (thisRequest = pendingRequest = loader()
.catch(err => { .catch(err => {
err = err instanceof Error ? err : new Error(String(err)) err = err instanceof Error ? err : new Error(String(err))
if (retryWhen(err) && retries < maxRetries) { if (userOnError) {
return retry(err) return new Promise((resolve, reject) => {
const userRetry = () => resolve(retry())
const userFail = () => reject(err)
userOnError(err, userRetry, userFail, retries + 1)
})
} else { } else {
throw err throw err
} }