You may have the browser execute periodically with setInterval
.
For example, periodically check whether the access token is valid or not and refresh it.
The browsers is busy executing JavaScript and updating the UI to display page content. We want not to affect these important tasks.
In this article, I will show you how to make a process run periodically without affecting important browser tasks as much as possible, using access token rotation as an example.
The code example shows the following processes by using React Hooks.
- check if the access token is valid while the browser is idle, and get a new token if it is invalid
- schedule the process 1 to be executed periodically, so that it will be executed again a few seconds after the process 1 is completed
- force checking to performed once every few seconds when the access token check is not running because the browser is too busy
Use the library idle-task
(v3.3.3) to run the process while the browser is idle.
https://github.com/hiroki0525/idle-task
This library internally uses a Web API called requestIdleCallback
.
Source Code
Before showing you the source code, let me first show you the screen we are going to implement.
If you leave the screen alone for a while, you will see a new token at the "now token is ~" point.
The implementation of the React Hooks is as follows.
import { useEffect, useState } from "react";
import { setIdleTask, cancelIdleTask } from "idle-task";
interface MockResponse {
readonly status: number;
readonly json: () => Promise<any>;
}
const mockFetchCheckAccessToken = async (
_token: string
): Promise<MockResponse> => {
if (Math.random() < 0.3) {
return {
status: 401,
json: async () => null
}
}
return {
status: 200,
json: async () => null
};
};
const mockFetchRefreshToken = async (
_oldToken: string
): Promise<MockResponse> => {
return {
status: 200,
json: async () =>
[... .Array(10)].map(() => Math.floor(Math.random() * 10)).join("")
};
};
const useAccessTokenWhenIdle = (): string => {
const [nowToken, setNowToken] = useState("none");
useEffect(() => {
const checkAccessToken = async (): Promise<void> => {
const checkTokenResponse = await mockFetchCheckAccessToken(nowToken);
if (checkTokenResponse.status === 200) {
return;
}
const newTokenResponse = await mockFetchRefreshToken(nowToken);
const newToken = await newTokenResponse.json();
console.log("refresh", newToken);
setNowToken(newToken);
};
const idleTaskId = setIdleTask(checkAccessToken, {
revalidateInterval: 5000
});
return () => {
cancelIdleTask(idleTaskId);
};
}, [nowToken]);
return nowToken;
};
export default useAccessTokenWhenIdle;
Here is the key code.
const idleTaskId = setIdleTask(checkAccessToken, {
revalidateInterval: 5000
});
With setIdleTask
, you can register a function that you want to execute while the browser is idle.
checkAccessToken
will be executed while the browser is idle.
The option revalidateInterval
is specified.
This will schedule the function to run again while the browser is idle after the specified time.
In this example, it means that schedule checkAccessToken
to run in 5 seconds while the browser is idle.
In this way, you can schedule the process to run periodically while the browser is idle.
- check if the access token is valid while the browser is idle, and get a new token if it is invalid
- schedule the process 1 to be executed periodically, so that it will be executed again a few seconds after the process 1 is completed
We have implemented 1 and 2 as described.
While 1 and 2 are sufficient, there is a concern.
It is that the browser is too busy and do not always become idle.
- force checking to performed once every few seconds when the access token check is not running because the browser is too busy
This is to guarantee that the process runs as much as possible.
Let's look at the code on the use side of the useAccessTokenWhenIdle
hooks.
import ". /styles.css";
import useAccessTokenWhenIdle from ". /useAccessTokenWhenIdle";
import { configureIdleTask } from "idle-task";
configureIdleTask({
debug: true,
interval: 1000 * 10
});
export default function App() {
const token = useAccessTokenWhenIdle();
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
Now token is {token}
</div>
);
}
The point is this.
configureIdleTask({
debug: true,
interval: 1000 * 10
});
The configureIdleTask
function is specified with an interval.
This will execute the function registered with setIdleTask at each specified interval with as little impact on browser performance as possible.
In this example, once every 10 seconds, if a checkAccessToken
registered with setIdleTask
remains in the queue managed by idle-task
, it will be executed without affecting browser performance.
If you want to guarantee the execution of as much processing as possible, specify the interval
of the configureIdleTask
in this way.
- force checking to performed once every few seconds when the access token check is not running because the browser is too busy
So we've got 3 implemented!!! 🎉
Summary
I have shown an example implementation of periodically rotating access tokens while the browser is idle.
Besides access token rotation, it could be used, for example, to save a draft of an article the user is editing.
If you have any bugs or questions about idle-task
, please contact us at GitHub issue.
https://github.com/hiroki0525/idle-task
This article will also help you to optimize your website.
https://dev.to/nuko_suke/improve-responsiveness-to-user-interactions-4a3p
If you found this helpful, please help someone else by sharing it or tagging someone in the comments!
Thanks!
Top comments (0)