-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(query-core): convert notifyManager from factory function to class
- Loading branch information
Showing
2 changed files
with
44 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,106 +1,90 @@ | ||
// TYPES | ||
|
||
type NotifyCallback = () => void | ||
|
||
type NotifyFunction = (callback: () => void) => void | ||
|
||
type BatchNotifyFunction = (callback: () => void) => void | ||
|
||
type BatchCallsCallback<T extends Array<unknown>> = (...args: T) => void | ||
|
||
type ScheduleFunction = (callback: () => void) => void | ||
|
||
export function createNotifyManager() { | ||
let queue: Array<NotifyCallback> = [] | ||
let transactions = 0 | ||
let notifyFn: NotifyFunction = (callback) => { | ||
export class NotifyManager { | ||
#queue: Array<NotifyCallback> = [] | ||
#transactions = 0 | ||
#notifyFn: NotifyFunction = (callback) => { | ||
callback() | ||
} | ||
let batchNotifyFn: BatchNotifyFunction = (callback: () => void) => { | ||
#batchNotifyFn: BatchNotifyFunction = (callback: () => void) => { | ||
callback() | ||
} | ||
let scheduleFn: ScheduleFunction = (cb) => setTimeout(cb, 0) | ||
#scheduleFn: ScheduleFunction = (callback) => setTimeout(callback, 0) | ||
#flush = () => { | ||
const originalQueue = this.#queue | ||
this.#queue = [] | ||
if (originalQueue.length) { | ||
this.#scheduleFn(() => { | ||
this.#batchNotifyFn(() => { | ||
originalQueue.forEach((callback) => { | ||
this.#notifyFn(callback) | ||
}) | ||
}) | ||
}) | ||
} | ||
} | ||
|
||
const setScheduler = (fn: ScheduleFunction) => { | ||
scheduleFn = fn | ||
setScheduler = (fn: ScheduleFunction) => { | ||
this.#scheduleFn = fn | ||
} | ||
|
||
const batch = <T>(callback: () => T): T => { | ||
batch = <T>(callback: () => T): T => { | ||
let result | ||
transactions++ | ||
this.#transactions++ | ||
try { | ||
result = callback() | ||
} finally { | ||
transactions-- | ||
if (!transactions) { | ||
flush() | ||
this.#transactions-- | ||
if (!this.#transactions) { | ||
this.#flush() | ||
} | ||
} | ||
return result | ||
} | ||
|
||
const schedule = (callback: NotifyCallback): void => { | ||
if (transactions) { | ||
queue.push(callback) | ||
schedule = (callback: NotifyCallback): void => { | ||
if (this.#transactions) { | ||
this.#queue.push(callback) | ||
} else { | ||
scheduleFn(() => { | ||
notifyFn(callback) | ||
this.#scheduleFn(() => { | ||
this.#notifyFn(callback) | ||
}) | ||
} | ||
} | ||
|
||
/** | ||
* All calls to the wrapped function will be batched. | ||
*/ | ||
const batchCalls = <T extends Array<unknown>>( | ||
batchCalls = <T extends Array<unknown>>( | ||
callback: BatchCallsCallback<T>, | ||
): BatchCallsCallback<T> => { | ||
return (...args) => { | ||
schedule(() => { | ||
this.schedule(() => { | ||
callback(...args) | ||
}) | ||
} | ||
} | ||
|
||
const flush = (): void => { | ||
const originalQueue = queue | ||
queue = [] | ||
if (originalQueue.length) { | ||
scheduleFn(() => { | ||
batchNotifyFn(() => { | ||
originalQueue.forEach((callback) => { | ||
notifyFn(callback) | ||
}) | ||
}) | ||
}) | ||
} | ||
} | ||
|
||
/** | ||
* Use this method to set a custom notify function. | ||
* This can be used to for example wrap notifications with `React.act` while running tests. | ||
*/ | ||
const setNotifyFunction = (fn: NotifyFunction) => { | ||
notifyFn = fn | ||
setNotifyFunction = (fn: NotifyFunction) => { | ||
this.#notifyFn = fn | ||
} | ||
|
||
/** | ||
* Use this method to set a custom function to batch notifications together into a single tick. | ||
* By default React Query will use the batch function provided by ReactDOM or React Native. | ||
*/ | ||
const setBatchNotifyFunction = (fn: BatchNotifyFunction) => { | ||
batchNotifyFn = fn | ||
setBatchNotifyFunction = (fn: BatchNotifyFunction) => { | ||
this.#batchNotifyFn = fn | ||
} | ||
|
||
return { | ||
batch, | ||
batchCalls, | ||
schedule, | ||
setNotifyFunction, | ||
setBatchNotifyFunction, | ||
setScheduler, | ||
} as const | ||
} | ||
|
||
// SINGLETON | ||
export const notifyManager = createNotifyManager() | ||
export const notifyManager = new NotifyManager() |