@tanstack/query-core
Version:
The framework agnostic core that powers TanStack Query
133 lines (132 loc) • 4.06 kB
JavaScript
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/notifyManager.ts
/**
* Default scheduling function used by the notify manager.
* Schedules the callback with the system's `setTimeout(callback, 0)`.
*/
const defaultScheduler = require("./timeoutManager.cjs").systemSetTimeoutZero;
/**
* Creates a notify manager, which schedules and batches notifications to subscribers. Query uses a
* single instance of it, exported as {@link notifyManager}.
* @returns A new notify manager.
*/
function createNotifyManager() {
let queue = [];
let transactions = 0;
let notifyFn = (callback) => {
callback();
};
let batchNotifyFn = (callback) => {
callback();
};
let scheduleFn = defaultScheduler;
const schedule = (callback) => {
if (transactions) queue.push(callback);
else scheduleFn(() => {
notifyFn(callback);
});
};
const flush = () => {
const originalQueue = queue;
queue = [];
if (originalQueue.length) scheduleFn(() => {
batchNotifyFn(() => {
originalQueue.forEach((callback) => {
notifyFn(callback);
});
});
});
};
return {
/**
* Batches all updates scheduled inside the passed callback.
* This is mainly used internally to optimize query client updating.
* Batches can be nested; the queue is only flushed once the outermost `batch` call finishes.
* The return value of `callback` is passed through.
* @param callback - The function to run in the batch.
* @returns The return value of `callback`.
*/
batch: (callback) => {
let result;
transactions++;
try {
result = callback();
} finally {
transactions--;
if (!transactions) flush();
}
return result;
},
/**
* All calls to the wrapped function will be batched.
* @param callback - The function to wrap.
* @returns A function that schedules a call to `callback` with the given arguments.
*/
batchCalls: (callback) => {
return (...args) => {
schedule(() => {
callback(...args);
});
};
},
/**
* Schedules a function to be run on the next batch.
* By default, the batch is run with a `setTimeout`, but this can be configured via `setScheduler`.
*/
schedule,
/**
* Use this method to set a custom notify function.
* This can be used to for example wrap notifications with `React.act` while running tests.
* @param fn - Receives each notification callback and must call it.
*/
setNotifyFunction: (fn) => {
notifyFn = fn;
},
/**
* Use this method to set a custom function to batch notifications together into a single tick.
* Framework adapters use this to plug in their own batching primitive, so that a single query
* update only triggers one re-render instead of one per subscriber.
* @param fn - Receives a function that runs a batch of notifications and must call it.
* @example
* ```ts
* import { notifyManager } from '@tanstack/query-core'
* import { batch } from 'solid-js'
*
* notifyManager.setBatchNotifyFunction(batch)
* ```
*/
setBatchNotifyFunction: (fn) => {
batchNotifyFn = fn;
},
/**
* Configures a custom callback that schedules when the next batch runs.
* The default behavior is `setTimeout(callback, 0)`.
* @param fn - Receives a callback that runs the next batch, and schedules it.
* @example
* ```ts
* import { notifyManager } from '@tanstack/query-core'
*
* // Schedule batches in the next microtask
* notifyManager.setScheduler(queueMicrotask)
*
* // Schedule batches before the next frame is rendered
* notifyManager.setScheduler(requestAnimationFrame)
*
* // Schedule batches some time in the future
* notifyManager.setScheduler((cb) => setTimeout(cb, 10))
* ```
*/
setScheduler: (fn) => {
scheduleFn = fn;
}
};
}
/**
* Handles scheduling and batching callbacks in TanStack Query.
*/
const notifyManager = createNotifyManager();
//#endregion
exports.createNotifyManager = createNotifyManager;
exports.defaultScheduler = defaultScheduler;
exports.notifyManager = notifyManager;
//# sourceMappingURL=notifyManager.cjs.map