未验证 提交 afc8ce4d 编写于 作者: S Shu Ding 提交者: GitHub

Fix idleTimeout error being thrown in route loader (#22775)

In the current implementation, `idleTimeout` will always be thrown even if it didn't time out and `Promise.race` was resolved. This causes the error `Error: Route did not complete loading` on every route transition and Chrome Devtools will pause code execution if you have "Pause on exceptions" enabled.

This PR adds `resolvePromiseWithTimeout` which does the same thing as `Promise.race` and `idleTimeout`, but it cancels the rejection when it resolves successfully, in which case the error won't be thrown.

Fixes #21543.
上级 33255b7f
......@@ -149,10 +149,29 @@ function appendScript(
})
}
function idleTimeout<T>(ms: number, err: Error): Promise<T> {
return new Promise((_resolve, reject) =>
requestIdleCallback(() => setTimeout(() => reject(err), ms))
)
// Resolve a promise that times out after given amount of milliseconds.
function resolvePromiseWithTimeout<T>(
p: Promise<T>,
ms: number,
err: Error
): Promise<T> {
return new Promise((resolve, reject) => {
let cancelled = false
p.then((r) => {
// Resolved, cancel the timeout
cancelled = true
resolve(r)
}).catch(reject)
requestIdleCallback(() =>
setTimeout(() => {
if (!cancelled) {
reject(err)
}
}, ms)
)
})
}
// TODO: stop exporting or cache the failure
......@@ -176,13 +195,12 @@ export function getClientBuildManifest(): Promise<ClientBuildManifest> {
cb && cb()
}
})
return Promise.race([
return resolvePromiseWithTimeout<ClientBuildManifest>(
onBuildManifest,
idleTimeout<ClientBuildManifest>(
MS_MAX_IDLE_DELAY,
markAssetError(new Error('Failed to load client build manifest'))
),
])
MS_MAX_IDLE_DELAY,
markAssetError(new Error('Failed to load client build manifest'))
)
}
interface RouteFiles {
......@@ -298,15 +316,14 @@ function createRouteLoader(assetPrefix: string): RouteLoader {
Promise.all(css.map(fetchStyleSheet)),
] as const)
const entrypoint: RouteEntrypoint = await Promise.race([
const entrypoint: RouteEntrypoint = await resolvePromiseWithTimeout(
this.whenEntrypoint(route),
idleTimeout<RouteLoaderEntry>(
MS_MAX_IDLE_DELAY,
markAssetError(
new Error(`Route did not complete loading: ${route}`)
)
),
])
MS_MAX_IDLE_DELAY,
markAssetError(
new Error(`Route did not complete loading: ${route}`)
)
)
const res: RouteLoaderEntry = Object.assign<
{ styles: RouteStyleSheet[] },
RouteEntrypoint
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册