presence-related fixes (#1361)
This fixes a bug where creating a page would fail if there were multiple pages with the same index. This also changes the store to use a throttled version of requestAnimationFrame. This should be good for relieving backpressure in situations where the store is updated many times in quick succession. It also makes testing a lot easier since it has the mocking logic built in. ### Change Type - [x] `patch` — Bug Fix ### Release Notes - Fix a bug where creating a page could throw an error in some multiplayer contexts.
This commit is contained in:
parent
9ccd0f480f
commit
d76446646c
7 changed files with 128 additions and 15 deletions
67
packages/utils/src/lib/raf.ts
Normal file
67
packages/utils/src/lib/raf.ts
Normal file
|
@ -0,0 +1,67 @@
|
|||
const isTest = () =>
|
||||
typeof process !== 'undefined' &&
|
||||
process.env.NODE_ENV === 'test' &&
|
||||
// @ts-expect-error
|
||||
!globalThis.__FORCE_RAF_IN_TESTS__
|
||||
|
||||
const rafQueue: Array<() => void> = []
|
||||
|
||||
const tick = () => {
|
||||
const queue = rafQueue.splice(0, rafQueue.length)
|
||||
for (const fn of queue) {
|
||||
fn()
|
||||
}
|
||||
}
|
||||
|
||||
let frame: number | undefined
|
||||
|
||||
function raf() {
|
||||
if (frame) {
|
||||
return
|
||||
}
|
||||
|
||||
frame = requestAnimationFrame(() => {
|
||||
frame = undefined
|
||||
tick()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a throttled version of the function that will only be called max once per frame.
|
||||
* @param fn - the fun to return a throttled version of
|
||||
* @returns
|
||||
* @internal
|
||||
*/
|
||||
export function rafThrottle(fn: () => void) {
|
||||
if (isTest()) {
|
||||
return fn
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (rafQueue.includes(fn)) {
|
||||
return
|
||||
}
|
||||
rafQueue.push(fn)
|
||||
raf()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the function on the next frame.
|
||||
* If the same fn is passed again before the next frame, it will still be called only once.
|
||||
* @param fn - the fun to call on the next animation frame
|
||||
* @returns
|
||||
* @internal
|
||||
*/
|
||||
export function throttledRaf(fn: () => void) {
|
||||
if (isTest()) {
|
||||
return fn()
|
||||
}
|
||||
|
||||
if (rafQueue.includes(fn)) {
|
||||
return
|
||||
}
|
||||
|
||||
rafQueue.push(fn)
|
||||
raf()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue