diff --git a/src/components/traffic.tsx b/src/components/traffic.tsx
index 26b8f55cb41c574abe35f805f806f51d3fcb39fe..51c1b83f2d4d3c2b7082f8cfe21bf037d7561e0e 100644
--- a/src/components/traffic.tsx
+++ b/src/components/traffic.tsx
@@ -1,29 +1,32 @@
-import axios from "axios";
+import { CancelTokenSource } from "axios";
 import { useEffect, useState } from "react";
+import { Box, Typography } from "@mui/material";
 import { ArrowDownward, ArrowUpward } from "@mui/icons-material";
 import parseTraffic from "../utils/parse-traffic";
-import { Typography } from "@mui/material";
-import { Box } from "@mui/system";
+import services from "../services";
 
 const Traffic = () => {
   const [traffic, setTraffic] = useState({ up: 0, down: 0 });
 
   useEffect(() => {
-    const onTraffic = () => {
-      axios({
-        url: `http://127.0.0.1:9090/traffic`,
-        method: "GET",
-        onDownloadProgress: (progressEvent) => {
-          const data = progressEvent.currentTarget.response || "";
-          const lastData = data.slice(data.trim().lastIndexOf("\n") + 1);
-          try {
-            if (lastData) setTraffic(JSON.parse(lastData));
-          } catch {}
-        },
-      }).catch(() => setTimeout(onTraffic, 500));
-    };
+    let timer: any = null;
+    let source: CancelTokenSource | null = null;
+
+    async function onTraffic() {
+      timer = null;
+      try {
+        source = await services.getTraffic(setTraffic);
+      } catch {
+        timer = setTimeout(onTraffic, 500);
+      }
+    }
 
     onTraffic();
+
+    return () => {
+      if (timer) clearTimeout(timer);
+      source?.cancel();
+    };
   }, []);
 
   const [up, upUnit] = parseTraffic(traffic.up);
@@ -45,7 +48,7 @@ const Traffic = () => {
 
   return (
     <Box width="110px">
-      <Box mb={2} display="flex" alignItems="center" whiteSpace="nowrap">
+      <Box mb={1.5} display="flex" alignItems="center" whiteSpace="nowrap">
         <ArrowUpward
           fontSize="small"
           color={+up > 0 ? "primary" : "disabled"}
diff --git a/src/services/base.ts b/src/services/base.ts
new file mode 100644
index 0000000000000000000000000000000000000000..23b2d38cd3ffea6f0ec07b00377baab5cb0d688d
--- /dev/null
+++ b/src/services/base.ts
@@ -0,0 +1,11 @@
+import axios from "axios";
+
+const axiosIns = axios.create({
+  baseURL: "http://127.0.0.1:9090",
+});
+
+axiosIns.interceptors.response.use((respone) => {
+  return respone.data;
+});
+
+export default axiosIns;
diff --git a/src/services/index.ts b/src/services/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a15cef0bde17916d2e0a58df508065943f506375
--- /dev/null
+++ b/src/services/index.ts
@@ -0,0 +1,5 @@
+import * as traffic from "./traffic";
+
+export default {
+  ...traffic,
+};
diff --git a/src/services/traffic.ts b/src/services/traffic.ts
new file mode 100644
index 0000000000000000000000000000000000000000..09e0e348d1fe4d4dbb0fde71d7cdfad611bf340d
--- /dev/null
+++ b/src/services/traffic.ts
@@ -0,0 +1,29 @@
+import axios from "axios";
+import axiosIns from "./base";
+
+export interface TrafficData {
+  up: number;
+  down: number;
+}
+
+/// Get the traffic stream
+export async function getTraffic(callback: (data: TrafficData) => void) {
+  const source = axios.CancelToken.source();
+
+  axiosIns.get("/traffic", {
+    cancelToken: source.token,
+    onDownloadProgress: (progressEvent) => {
+      const data = progressEvent.currentTarget.response || "";
+      const lastData = data.slice(data.trim().lastIndexOf("\n") + 1);
+
+      if (!lastData) callback({ up: 0, down: 0 });
+      try {
+        callback(JSON.parse(lastData) as TrafficData);
+      } catch {
+        callback({ up: 0, down: 0 });
+      }
+    },
+  });
+
+  return source;
+}