wip: retry suspense async deps from resolved dep instead of root

This commit is contained in:
Evan You 2019-09-10 10:09:04 -04:00
parent 0d176ebf2a
commit c9e625864a
2 changed files with 27 additions and 44 deletions

View File

@ -610,12 +610,8 @@ export function createRenderer<
) { ) {
if (n1 == null) { if (n1 == null) {
const contentContainer = hostCreateElement('div') const contentContainer = hostCreateElement('div')
const suspense = (n2.suspense = createSuspenseBoundary(
n2,
parentSuspense
))
suspense.onRetry(() => { function retry() {
processFragment( processFragment(
suspense.oldSubTree, suspense.oldSubTree,
suspense.subTree as HostVNode, suspense.subTree as HostVNode,
@ -631,9 +627,9 @@ export function createRenderer<
} else { } else {
suspense.resolve() suspense.resolve()
} }
}) }
suspense.onResolve(() => { function resolve() {
// unmount fallback tree // unmount fallback tree
unmount(suspense.fallbackTree as HostVNode, parentComponent, true) unmount(suspense.fallbackTree as HostVNode, parentComponent, true)
// move content from off-dom container to actual container // move content from off-dom container to actual container
@ -656,7 +652,14 @@ export function createRenderer<
queuePostFlushCb(suspense.bufferedJobs) queuePostFlushCb(suspense.bufferedJobs)
} }
suspense.isResolved = true suspense.isResolved = true
}) }
const suspense = (n2.suspense = createSuspenseBoundary(
n2,
parentSuspense,
retry,
resolve
))
// TODO pass it down as an arg instead // TODO pass it down as an arg instead
if (parentComponent) { if (parentComponent) {
@ -749,17 +752,7 @@ export function createRenderer<
return return
} }
// a resolved async component, on successful re-entry. if (shouldUpdateComponent(n1, n2, optimized)) {
// pickup the mounting process and setup render effect
if (!instance.update) {
setupRenderEffect(instance, n2, container, anchor, isSVG)
} else if (
shouldUpdateComponent(n1, n2, optimized) ||
// TODO use context suspense
(__FEATURE_SUSPENSE__ &&
instance.provides.suspense &&
!(instance.provides.suspense as any).isResolved)
) {
// normal update // normal update
instance.next = n2 instance.next = n2
instance.update() instance.update()
@ -814,11 +807,15 @@ export function createRenderer<
throw new Error('Async component without a suspense boundary!') throw new Error('Async component without a suspense boundary!')
} }
suspense.deps++ suspense.deps++
instance.asyncDep.then(res => { instance.asyncDep.then(asyncSetupResult => {
instance.asyncResolved = true
handleSetupResult(instance, res)
suspense.deps-- suspense.deps--
suspense.retry() // retry from this component
instance.asyncResolved = true
handleSetupResult(instance, asyncSetupResult)
setupRenderEffect(instance, initialVNode, container, anchor, isSVG)
if (suspense.deps === 0) {
suspense.resolve()
}
}) })
// give it a placeholder // give it a placeholder
const placeholder = (instance.subTree = createVNode(Empty)) const placeholder = (instance.subTree = createVNode(Empty))
@ -1276,7 +1273,7 @@ export function createRenderer<
hostInsert(vnode.el as HostNode, container, anchor) hostInsert(vnode.el as HostNode, container, anchor)
const children = vnode.children as HostVNode[] const children = vnode.children as HostVNode[]
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
hostInsert(children[i].el as HostNode, container, anchor) move(children[i], container, anchor)
} }
hostInsert(vnode.anchor as HostNode, container, anchor) hostInsert(vnode.anchor as HostNode, container, anchor)
} else { } else {

View File

@ -16,19 +16,17 @@ export interface SuspenseBoundary<
deps: number deps: number
isResolved: boolean isResolved: boolean
bufferedJobs: Function[] bufferedJobs: Function[]
onRetry(fn: Function): void
retry(): void retry(): void
onResolve(fn: Function): void
resolve(): void resolve(): void
} }
export function createSuspenseBoundary<HostNode, HostElement>( export function createSuspenseBoundary<HostNode, HostElement>(
vnode: VNode<HostNode, HostElement>, vnode: VNode<HostNode, HostElement>,
parent: SuspenseBoundary<HostNode, HostElement> | null parent: SuspenseBoundary<HostNode, HostElement> | null,
retry: () => void,
resolve: () => void
): SuspenseBoundary<HostNode, HostElement> { ): SuspenseBoundary<HostNode, HostElement> {
let retry: Function return {
let resolve: Function
const suspense: SuspenseBoundary<HostNode, HostElement> = {
vnode, vnode,
parent, parent,
deps: 0, deps: 0,
@ -38,19 +36,7 @@ export function createSuspenseBoundary<HostNode, HostElement>(
oldFallbackTree: null, oldFallbackTree: null,
isResolved: false, isResolved: false,
bufferedJobs: [], bufferedJobs: [],
onRetry(fn: Function) { retry,
retry = fn resolve
},
retry() {
retry()
},
onResolve(fn: Function) {
resolve = fn
},
resolve() {
resolve()
}
} }
return suspense
} }