Skip to content

Commit 9b0afa6

Browse files
authored
Remove failed prefetch requests from in-flight array (#2500)
* wip * wip * wip * TS * Update prefetched.ts
1 parent ff3caa9 commit 9b0afa6

File tree

10 files changed

+94
-4
lines changed

10 files changed

+94
-4
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"dev:test-app:react": "pnpx concurrently -c \"#fdba74,#34d399\" \"cd tests/app && PACKAGE=react pnpm serve:watch\" \"cd packages/react/test-app && pnpm run dev\" --names=server,vite",
1010
"dev:test-app:svelte": "pnpx concurrently -c \"#fdba74,#34d399\" \"cd tests/app && PACKAGE=svelte pnpm serve:watch\" \"cd packages/svelte/test-app && pnpm run dev\" --names=server,vite",
1111
"dev:test-app:vue": "pnpx concurrently -c \"#fdba74,#34d399\" \"cd tests/app && PACKAGE=vue3 pnpm serve:watch\" \"cd packages/vue3/test-app && pnpm run dev\" --names=server,vite",
12+
"type-check:test-app": "pnpm -r --filter './packages/*/test-app' type-check",
1213
"type-check:test-app:react": "cd packages/react/test-app && pnpm run type-check",
1314
"type-check:test-app:svelte": "cd packages/svelte/test-app && pnpm run type-check",
1415
"type-check:test-app:vue": "cd packages/vue3/test-app && pnpm run type-check",

packages/core/src/prefetched.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ class PrefetchedRequests {
5555
onPrefetchResponse(response) {
5656
resolve(response)
5757
},
58+
onPrefetchError(error) {
59+
prefetchedRequests.removeFromInFlight(params)
60+
reject(error)
61+
},
5862
})
5963
}).then((response) => {
6064
this.remove(params)
@@ -69,10 +73,7 @@ class PrefetchedRequests {
6973
})
7074

7175
this.scheduleForRemoval(params, expires)
72-
73-
this.inFlightRequests = this.inFlightRequests.filter((prefetching) => {
74-
return !this.paramsAreEqual(prefetching.params, params)
75-
})
76+
this.removeFromInFlight(params)
7677

7778
response.handlePrefetch()
7879

@@ -105,6 +106,12 @@ class PrefetchedRequests {
105106
this.clearTimer(params)
106107
}
107108

109+
protected removeFromInFlight(params: ActiveVisit): void {
110+
this.inFlightRequests = this.inFlightRequests.filter((prefetching) => {
111+
return !this.paramsAreEqual(prefetching.params, params)
112+
})
113+
}
114+
108115
protected extractStaleValues(cacheFor: PrefetchOptions['cacheFor']): [number, number] {
109116
const [stale, expires] = this.cacheForToStaleAndExpires(cacheFor)
110117

packages/core/src/request.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ export class Request {
7272
}
7373

7474
if (fireExceptionEvent(error)) {
75+
if (originallyPrefetch) {
76+
this.requestParams.onPrefetchError(error)
77+
}
78+
7579
return Promise.reject(error)
7680
}
7781
})

packages/core/src/requestParams.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export class RequestParams {
3232
...params,
3333
...wrappedCallbacks,
3434
onPrefetchResponse: params.onPrefetchResponse || (() => {}),
35+
onPrefetchError: params.onPrefetchError || (() => {}),
3536
}
3637
}
3738
//
@@ -95,6 +96,12 @@ export class RequestParams {
9596
}
9697
}
9798

99+
public onPrefetchError(error: Error) {
100+
if (this.params.onPrefetchError) {
101+
this.params.onPrefetchError(error)
102+
}
103+
}
104+
98105
public all() {
99106
return this.params
100107
}

packages/core/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ export type ActiveVisit<T extends RequestPayload = RequestPayload> = PendingVisi
336336

337337
export type InternalActiveVisit = ActiveVisit & {
338338
onPrefetchResponse?: (response: Response) => void
339+
onPrefetchError?: (error: Error) => void
339340
}
340341

341342
export type VisitId = unknown
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { router } from '@inertiajs/react'
2+
3+
export default function AfterError() {
4+
const prefetchPage = () => {
5+
router.prefetch('/prefetch/swr/1', { method: 'get' }, { cacheFor: 5000 })
6+
}
7+
8+
const visitPage = () => {
9+
router.visit('/prefetch/swr/1')
10+
}
11+
12+
return (
13+
<div>
14+
<button onClick={prefetchPage}>Prefetch Page</button>
15+
<button onClick={visitPage}>Visit Page</button>
16+
</div>
17+
)
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<script lang="ts">
2+
import { router } from '@inertiajs/svelte'
3+
4+
const prefetchPage = () => {
5+
router.prefetch('/prefetch/swr/1', { method: 'get' }, { cacheFor: 5000 })
6+
}
7+
8+
const visitPage = () => {
9+
router.visit('/prefetch/swr/1')
10+
}
11+
</script>
12+
13+
<div>
14+
<button on:click={prefetchPage}>Prefetch Page</button>
15+
<button on:click={visitPage}>Visit Page</button>
16+
</div>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<script setup lang="ts">
2+
import { router } from '@inertiajs/vue3'
3+
4+
const prefetchPage = () => {
5+
router.prefetch('/prefetch/swr/1', { method: 'get' }, { cacheFor: 5000 })
6+
}
7+
8+
const visitPage = () => {
9+
router.visit('/prefetch/swr/1')
10+
}
11+
</script>
12+
13+
<template>
14+
<div>
15+
<button @click="prefetchPage">Prefetch Page</button>
16+
<button @click="visitPage">Visit Page</button>
17+
</div>
18+
</template>

tests/app/server.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ app.get('/poll/hook', (req, res) => inertia.render(req, res, { component: 'Poll/
235235
app.get('/poll/hook/manual', (req, res) => inertia.render(req, res, { component: 'Poll/HookManual', props: {} }))
236236
app.get('/poll/router/manual', (req, res) => inertia.render(req, res, { component: 'Poll/RouterManual', props: {} }))
237237

238+
app.get('/prefetch/after-error', (req, res) => {
239+
inertia.render(req, res, { component: 'Prefetch/AfterError' })
240+
})
241+
238242
app.get('/prefetch/:pageNumber', (req, res) => {
239243
inertia.render(req, res, {
240244
component: 'Prefetch/Page',

tests/prefetch.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,20 @@ test('can cache links with single cache value', async ({ page }) => {
158158
await expect(lastLoaded2).not.toBe(lastLoaded2Fresh)
159159
})
160160

161+
test('can visit the page when prefetching has failed due to network error', async ({ page, browser }) => {
162+
await page.goto('prefetch/after-error')
163+
164+
page.context().setOffline(true)
165+
await page.getByRole('button', { name: 'Prefetch Page' }).click()
166+
167+
page.context().setOffline(false)
168+
169+
requests.listen(page)
170+
await page.getByRole('button', { name: 'Visit Page' }).click()
171+
172+
await isPrefetchSwrPage(page, 1)
173+
})
174+
161175
test.skip('can do SWR when the link cacheFor prop has two values', async ({ page }) => {
162176
await page.goto('prefetch/swr/1')
163177

0 commit comments

Comments
 (0)