Hi guys! Today I am going to tell you what is AbortController
, why you possible need it and how it can improve the performance of your application.
Introduction
In a small IT chat, I conducted a survey and it turned out that only 9% of web developers used it in a real project, and 64% of web developers do not know what it is at all.
So let's get started!
The AbortController
interface represents a controller object that allows you to abort one or more Web requests as and when desired.
This is a very simple interface that consists of the signal
property and the abort
method
const controller = new AbortController();
const signal = controller.signal;
const abort = controller.abort;
We pass signal
to the call method: fetch(url, { signal })
and with abort()
this call can be stopped
Examples
Fetch
This simple code our application:
export default function App() {
const [url, setUrl] = useState("users");
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
fetch(`https://jsonplaceholder.typicode.com/${url}`)
.then((res) => res.json())
.then((res) => {
setData(res);
setLoading(false);
});
}, [url]);
return (
<div className="App">
<div className="nav">
<Link to="/users" onClick={() => setUrl("users")}>
users
</Link>
<Link to="/todos" onClick={() => setUrl("todos")}>
todos
</Link>
<Link to="/posts" onClick={() => setUrl("posts")}>
posts
</Link>
</div>
<div className="page">
<Switch>
<Route path="/users" component={() => <div>Users page</div>} />
<Route path="/todos" component={() => <div>Todos page</div>} />
<Route path="/posts" component={() => <div>Posts page</div>} />
</Switch>
{loading ? (
"loading..."
) : (
<ul>
{data?.splice(0, 5).map((item) => (
<li key={item.id}>{item?.name || item?.title}</li>
))}
</ul>
)}
</div>
</div>
);
}
and it works like this:
As you can see all 3 requests reach the target and are displayed on the screen in turn
We can imagine a situation where the user navigates through our menu faster than the requests have time to be processed on the server, that mean we do unnecessary requests
For example: the user come to the "/user" page, a request has begun, next user come to the "/post" page, at this moment we assume that he no longer needs the "/user" page, and this request can be canceled and not load the server
This is how the code looks like with AbortController, I changed only useEffect:
useEffect(() => {
const controller = new AbortController();
const signal = controller.signal;
setLoading(true);
fetch(`https://jsonplaceholder.typicode.com/${url}`, { signal })
.then((res) => res.json())
.then((res) => {
setData(res);
setLoading(false);
});
return () => {
controller.abort();
};
}, [url]);
and that's what happened:
Unnecessary requests have been cancelled!
This is the main point of performance!
Axios
identical with fetch
const controller = new AbortController();
axios.get('/user', { signal: controller.signal })
GQL
GQL have almost the same way, but you need to use useRef
In the following example we cancel the request when we leave the page:
const controllerRef = useRef(new AbortController());
const [getUser, { data }] = useLazyQuery(USER_QUERY, {
context: {
fetchOptions: {
signal: controllerRef.current.signal,
},
},
});
useEffect(() => {
return () => controllerRef.current.abort();
}, []);
Conclusion
AbortController is a simple and effective way to improve performance which you can try in your projects, good luck!
Top comments (0)