Skip to content

Commit 1ca4e82

Browse files
committed
centralize poll logic in poll class and fix throttling
1 parent 5cbf302 commit 1ca4e82

File tree

7 files changed

+87
-64
lines changed

7 files changed

+87
-64
lines changed

packages/core/src/poll.ts

+25-25
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,21 @@ import { PollOptions } from './types'
22

33
export class Poll {
44
protected id: number | null = null
5-
protected inBackground = false
5+
protected throttle = false
66
protected keepAlive = false
7-
protected currentInterval: number
8-
protected originalInterval: number
7+
protected cb: VoidFunction
8+
protected interval: number
9+
protected cbCount = 0
910

1011
constructor(interval: number, cb: VoidFunction, options: PollOptions) {
1112
this.keepAlive = options.keepAlive || false
1213

13-
this.currentInterval = interval
14-
this.originalInterval = interval
14+
this.cb = cb
15+
this.interval = interval
1516

16-
this.start(interval, cb)
17+
if (options.autoStart || true) {
18+
this.start()
19+
}
1720
}
1821

1922
public stop() {
@@ -22,28 +25,25 @@ export class Poll {
2225
}
2326
}
2427

25-
public isInBackground(hidden: boolean) {
26-
this.inBackground = this.keepAlive ? false : hidden
27-
28-
if (this.inBackground) {
29-
// Throttle requests by 95% when the page is in the background
30-
this.currentInterval = Math.round(this.originalInterval / 0.05)
31-
} else {
32-
// Otherwise, restore the original interval
33-
this.currentInterval = this.originalInterval
34-
}
35-
}
28+
public start() {
29+
this.stop()
3630

37-
protected start(interval: number, cb: VoidFunction) {
3831
this.id = window.setInterval(() => {
39-
if (this.currentInterval === interval) {
40-
cb()
41-
return
32+
if (!this.throttle || this.cbCount % 10 === 0) {
33+
this.cb()
34+
}
35+
36+
if (this.throttle) {
37+
this.cbCount++
4238
}
39+
}, this.interval)
40+
}
4341

44-
// The visibility has changed, so we need to adjust the interval
45-
this.stop()
46-
this.start(this.currentInterval, cb)
47-
}, interval)
42+
public isInBackground(hidden: boolean) {
43+
this.throttle = this.keepAlive ? false : hidden
44+
45+
if (this.throttle) {
46+
this.cbCount = 0
47+
}
4848
}
4949
}

packages/core/src/polls.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,22 @@ class Polls {
88
this.setupVisibilityListener()
99
}
1010

11-
public add(interval: number, cb: VoidFunction, options: PollOptions): VoidFunction {
11+
public add(
12+
interval: number,
13+
cb: VoidFunction,
14+
options: PollOptions,
15+
): {
16+
stop: VoidFunction
17+
start: VoidFunction
18+
} {
1219
const poll = new Poll(interval, cb, options)
1320

1421
this.polls.push(poll)
1522

16-
return () => poll.stop()
23+
return {
24+
stop: () => poll.stop(),
25+
start: () => poll.start(),
26+
}
1727
}
1828

1929
public clear() {

packages/core/src/router.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export class Router {
124124
this.syncRequestStream.cancelInFlight()
125125
}
126126

127-
public poll(interval: number, requestOptions: ReloadOptions = {}, options: PollOptions = {}): VoidFunction {
127+
public poll(interval: number, requestOptions: ReloadOptions = {}, options: PollOptions = {}) {
128128
return polls.add(interval, () => this.reload(requestOptions), { keepAlive: options.keepAlive || false })
129129
}
130130

packages/core/src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ export type ReloadOptions = Omit<VisitOptions, 'preserveScroll' | 'preserveState
190190

191191
export type PollOptions = {
192192
keepAlive?: boolean
193+
autoStart?: boolean
193194
}
194195

195196
export type VisitHelperOptions = Omit<VisitOptions, 'method' | 'data'>

packages/react/src/usePoll.ts

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { PollOptions, ReloadOptions, router } from '@inertiajs/core'
2+
import { useEffect } from 'react'
3+
4+
export default function usePoll(interval: number, requestOptions: ReloadOptions = {}, options: PollOptions = {}) {
5+
const { stop, start } = router.poll(interval, requestOptions, {
6+
...options,
7+
autoStart: false,
8+
})
9+
10+
useEffect(() => {
11+
if (options.autoStart) {
12+
start()
13+
}
14+
15+
return () => stop()
16+
}, [])
17+
18+
return {
19+
stop,
20+
start,
21+
}
22+
}

packages/vue3/src/usePoll.ts

+7-19
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,21 @@ import { onMounted, onUnmounted } from 'vue'
55
export default function usePoll(
66
interval: number,
77
requestOptions: ReloadOptions = {},
8-
options: PollOptions & {
9-
startOnMount?: boolean
10-
} = {
8+
options: PollOptions = {
119
keepAlive: false,
12-
startOnMount: true,
10+
autoStart: true,
1311
},
1412
): {
1513
stop: VoidFunction
1614
start: VoidFunction
1715
} {
18-
let stopFunc: VoidFunction
19-
20-
options.startOnMount ??= true
21-
22-
const stop = () => {
23-
if (stopFunc) {
24-
stopFunc()
25-
}
26-
}
27-
28-
const start = () => {
29-
stop()
30-
stopFunc = router.poll(interval, requestOptions, options)
31-
}
16+
const { stop, start } = router.poll(interval, requestOptions, {
17+
...options,
18+
autoStart: false,
19+
})
3220

3321
onMounted(() => {
34-
if (options.startOnMount) {
22+
if (options.autoStart) {
3523
start()
3624
}
3725
})

playgrounds/vue3/resources/js/Pages/Poll.vue

+19-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<script lang="ts">
22
import usePoll from '../../../../../packages/vue3/src/usePoll'
33
import Layout from '../Components/Layout.vue'
4+
import TestGrid from '../Components/TestGrid.vue'
5+
import TestGridItem from '../Components/TestGridItem.vue'
46
export default { layout: Layout }
57
</script>
68

@@ -17,7 +19,7 @@ const userPollCount = ref(0)
1719
const hookPollCount = ref(0)
1820
const companyPollCount = ref(0)
1921
20-
const trigegerAsyncRedirect = () => {
22+
const triggerAsyncRedirect = () => {
2123
router.get(
2224
'/elsewhere',
2325
{},
@@ -38,7 +40,7 @@ const { start, stop } = usePoll(
3840
},
3941
{
4042
keepAlive: true,
41-
startOnMount: false,
43+
autoStart: false,
4244
},
4345
)
4446
@@ -47,7 +49,7 @@ onMounted(() => {
4749
start()
4850
}, 2000)
4951
50-
const stopUserPolling = router.poll(
52+
const { stop: stopUserPolling } = router.poll(
5153
1000,
5254
{
5355
only: ['users'],
@@ -75,24 +77,24 @@ onMounted(() => {
7577
<template>
7678
<Head title="Async Request" />
7779
<h1 class="text-3xl">Poll</h1>
78-
<div class="flex mt-6 space-x-6">
79-
<div>
80-
<div class="mb-2 font-bold">User Poll Request Count: {{ userPollCount }}</div>
80+
<TestGrid>
81+
<TestGridItem>
82+
<template #title> User Poll Request Count: {{ userPollCount }} </template>
8183
<div v-for="user in users">
8284
<div>{{ user }}</div>
8385
</div>
84-
</div>
85-
<div>
86-
<div class="mb-2 font-bold">Companies Poll Request Count: {{ companyPollCount }}</div>
86+
</TestGridItem>
87+
<TestGridItem>
88+
<template #title> Companies Poll Request Count: {{ companyPollCount }} </template>
8789
<div v-for="company in companies">
8890
<div>{{ company }}</div>
8991
</div>
90-
</div>
91-
<div>
92-
<div class="mb-2 font-bold">Hook Count: {{ hookPollCount }}</div>
93-
</div>
94-
<div>
95-
<button @click="trigegerAsyncRedirect">Trigger Async Redirect</button>
96-
</div>
97-
</div>
92+
</TestGridItem>
93+
<TestGridItem>
94+
<template #title> Hook Poll Request Count: {{ hookPollCount }} </template>
95+
</TestGridItem>
96+
<TestGridItem>
97+
<button @click="triggerAsyncRedirect">Trigger Async Redirect</button>
98+
</TestGridItem>
99+
</TestGrid>
98100
</template>

0 commit comments

Comments
 (0)