Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option for queries to pause polling when unfocused #4055

Merged
merged 11 commits into from
Jan 24, 2024
Next Next commit
Updated middleware to handle poll skipping
Changes made to the polling middleware to handle the situation when the page is out of focus. The code now includes a check to see whether to skip polling if the page is out of focus. Restructured the return from 'findLowestPollingInterval' function to include 'skipPollOnFocusLost' flag.
  • Loading branch information
riqts committed Jan 24, 2024
commit 2fe59156161312be7502d426c7809dce3621d76a
45 changes: 27 additions & 18 deletions packages/toolkit/src/query/core/buildMiddleware/polling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,35 +53,38 @@ export const buildPollingHandler: InternalHandlerBuilder = ({
{ queryCacheKey }: QuerySubstateIdentifier,
api: SubMiddlewareApi
) {
const state = api.getState()[reducerPath]
const querySubState = state.queries[queryCacheKey]
const subscriptions = internalState.currentSubscriptions[queryCacheKey]
const state = api.getState()[reducerPath];
const querySubState = state.queries[queryCacheKey];
const subscriptions = internalState.currentSubscriptions[queryCacheKey];

if (!querySubState || querySubState.status === QueryStatus.uninitialized)
return
return;

const lowestPollingInterval = findLowestPollingInterval(subscriptions)
if (!Number.isFinite(lowestPollingInterval)) return
const { lowestPollingInterval, skipPollOnFocusLost } = findLowestPollingInterval(subscriptions);
if (!Number.isFinite(lowestPollingInterval)) return;

const currentPoll = currentPolls[queryCacheKey]
const currentPoll = currentPolls[queryCacheKey];

if (currentPoll?.timeout) {
clearTimeout(currentPoll.timeout)
currentPoll.timeout = undefined
clearTimeout(currentPoll.timeout);
currentPoll.timeout = undefined;
}

const nextPollTimestamp = Date.now() + lowestPollingInterval
const nextPollTimestamp = Date.now() + lowestPollingInterval;

const currentInterval: typeof currentPolls[number] = (currentPolls[
queryCacheKey
] = {
// Always update the polling interval
currentPolls[queryCacheKey] = {
nextPollTimestamp,
pollingInterval: lowestPollingInterval,
timeout: setTimeout(() => {
currentInterval!.timeout = undefined
api.dispatch(refetchQuery(querySubState, queryCacheKey))
// Conditionally dispatch the query
if (document.hasFocus() || !skipPollOnFocusLost) {
riqts marked this conversation as resolved.
Show resolved Hide resolved
api.dispatch(refetchQuery(querySubState, queryCacheKey));
}
// Regardless of dispatch, set up the next poll
startNextPoll({ queryCacheKey }, api);
}, lowestPollingInterval),
})
};
}

function updatePollingInterval(
Expand All @@ -96,7 +99,7 @@ export const buildPollingHandler: InternalHandlerBuilder = ({
return
}

const lowestPollingInterval = findLowestPollingInterval(subscriptions)
const { lowestPollingInterval } = findLowestPollingInterval(subscriptions)

if (!Number.isFinite(lowestPollingInterval)) {
cleanupPollForKey(queryCacheKey)
Expand Down Expand Up @@ -126,17 +129,23 @@ export const buildPollingHandler: InternalHandlerBuilder = ({
}

function findLowestPollingInterval(subscribers: Subscribers = {}) {
let skipPollOnFocusLost: boolean | undefined = false
let lowestPollingInterval = Number.POSITIVE_INFINITY
for (let key in subscribers) {
if (!!subscribers[key].pollingInterval) {
lowestPollingInterval = Math.min(
subscribers[key].pollingInterval!,
lowestPollingInterval
)
skipPollOnFocusLost = subscribers[key].skipPollOnFocusLost
EskiMojo14 marked this conversation as resolved.
Show resolved Hide resolved
}
}

return lowestPollingInterval
return {
lowestPollingInterval,
skipPollOnFocusLost,
}
}

return handler
}