Skip to content

Commit

Permalink
refactor(core): refactor internals from classes to a functions (#3066)
Browse files Browse the repository at this point in the history
* refactor(core): refactor retryer from a class to a function

* refactor(core): refactor notifyManager from a class to a function

* refactor(core): refactor notifyManager from a class to a function

remove outdated comment
  • Loading branch information
TkDodo committed Dec 10, 2021
1 parent 14da2c8 commit 1247d7b
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 189 deletions.
6 changes: 3 additions & 3 deletions src/core/mutation.ts
Expand Up @@ -4,7 +4,7 @@ import type { MutationObserver } from './mutationObserver'
import { getLogger } from './logger'
import { notifyManager } from './notifyManager'
import { Removable } from './removable'
import { canFetch, Retryer } from './retryer'
import { canFetch, Retryer, createRetryer } from './retryer'
import { noop } from './utils'

// TYPES
Expand Down Expand Up @@ -90,7 +90,7 @@ export class Mutation<

private observers: MutationObserver<TData, TError, TVariables, TContext>[]
private mutationCache: MutationCache
private retryer?: Retryer<TData, TError>
private retryer?: Retryer<TData>

constructor(config: MutationConfig<TData, TError, TVariables, TContext>) {
super()
Expand Down Expand Up @@ -262,7 +262,7 @@ export class Mutation<
}

private executeMutation(): Promise<TData> {
this.retryer = new Retryer({
this.retryer = createRetryer({
fn: () => {
if (!this.options.mutationFn) {
return Promise.reject('No mutationFn found')
Expand Down
82 changes: 39 additions & 43 deletions src/core/notifyManager.ts
Expand Up @@ -8,66 +8,55 @@ type NotifyFunction = (callback: () => void) => void

type BatchNotifyFunction = (callback: () => void) => void

// CLASS

export class NotifyManager {
private queue: NotifyCallback[]
private transactions: number
private notifyFn: NotifyFunction
private batchNotifyFn: BatchNotifyFunction

constructor() {
this.queue = []
this.transactions = 0

this.notifyFn = (callback: () => void) => {
callback()
}

this.batchNotifyFn = (callback: () => void) => {
callback()
}
export function createNotifyManager() {
let queue: NotifyCallback[] = []
let transactions = 0
let notifyFn: NotifyFunction = callback => {
callback()
}
let batchNotifyFn: BatchNotifyFunction = (callback: () => void) => {
callback()
}

batch<T>(callback: () => T): T {
this.transactions++
const batch = <T>(callback: () => T): T => {
transactions++
const result = callback()
this.transactions--
if (!this.transactions) {
this.flush()
transactions--
if (!transactions) {
flush()
}
return result
}

schedule(callback: NotifyCallback): void {
if (this.transactions) {
this.queue.push(callback)
const schedule = (callback: NotifyCallback): void => {
if (transactions) {
queue.push(callback)
} else {
scheduleMicrotask(() => {
this.notifyFn(callback)
notifyFn(callback)
})
}
}

/**
* All calls to the wrapped function will be batched.
*/
batchCalls<T extends Function>(callback: T): T {
const batchCalls = <T extends Function>(callback: T): T => {
return ((...args: any[]) => {
this.schedule(() => {
schedule(() => {
callback(...args)
})
}) as any
}

flush(): void {
const queue = this.queue
this.queue = []
if (queue.length) {
const flush = (): void => {
const originalQueue = queue
queue = []
if (originalQueue.length) {
scheduleMicrotask(() => {
this.batchNotifyFn(() => {
queue.forEach(callback => {
this.notifyFn(callback)
batchNotifyFn(() => {
originalQueue.forEach(callback => {
notifyFn(callback)
})
})
})
Expand All @@ -78,19 +67,26 @@ export class NotifyManager {
* Use this method to set a custom notify function.
* This can be used to for example wrap notifications with `React.act` while running tests.
*/
setNotifyFunction(fn: NotifyFunction) {
this.notifyFn = fn
const setNotifyFunction = (fn: NotifyFunction) => {
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.
*/
setBatchNotifyFunction(fn: BatchNotifyFunction) {
this.batchNotifyFn = fn
const setBatchNotifyFunction = (fn: BatchNotifyFunction) => {
batchNotifyFn = fn
}

return {
batch,
batchCalls,
schedule,
setNotifyFunction,
setBatchNotifyFunction,
} as const
}

// SINGLETON

export const notifyManager = new NotifyManager()
export const notifyManager = createNotifyManager()
6 changes: 3 additions & 3 deletions src/core/query.ts
Expand Up @@ -21,7 +21,7 @@ import type { QueryCache } from './queryCache'
import type { QueryObserver } from './queryObserver'
import { notifyManager } from './notifyManager'
import { getLogger } from './logger'
import { Retryer, isCancelledError, canFetch } from './retryer'
import { Retryer, isCancelledError, canFetch, createRetryer } from './retryer'
import { Removable } from './removable'

// TYPES
Expand Down Expand Up @@ -158,7 +158,7 @@ export class Query<

private cache: QueryCache
private promise?: Promise<TData>
private retryer?: Retryer<TData, TError>
private retryer?: Retryer<TData>
private observers: QueryObserver<any, any, any, any, any>[]
private defaultOptions?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
private abortSignalConsumed: boolean
Expand Down Expand Up @@ -431,7 +431,7 @@ export class Query<
}

// Try to fetch the data
this.retryer = new Retryer({
this.retryer = createRetryer({
fn: context.fetchFn as () => TData,
abort: abortController?.abort?.bind(abortController),
onSuccess: data => {
Expand Down

0 comments on commit 1247d7b

Please sign in to comment.