mirror of
https://github.com/eclipse-mosquitto/mosquitto.git
synced 2026-09-25 02:33:51 +08:00
Dashboard: Add abort controller to abort in-flight request on navigation
Known bug: abort controller logic doesn't work properly in firefox because a general network error is fired before the abort callback. We would probably need to track the navigation-click event to overcome this. Signed-off-by: Serhii Orlivskyi <serhii.orlivskyi@cedalo.com> (Cedalo GmbH)
This commit is contained in:
committed by
Roger Light
parent
502d2dcc19
commit
9fc336b894
@@ -1,5 +1,8 @@
|
||||
class MosquittoDashboard {
|
||||
constructor(headless = false) {
|
||||
this.abort = new AbortController();
|
||||
registerAbortController(this.abort, this);
|
||||
|
||||
this.headlessMode = !!headless;
|
||||
|
||||
!this.headlessMode && window.Chart.register(window.ChartZoom); // chartjs comes from lib/
|
||||
@@ -1483,7 +1486,10 @@ class MosquittoDashboard {
|
||||
const nowTimestampMilliseconds = new Date().getTime();
|
||||
let sysTopics = null;
|
||||
try {
|
||||
sysTopics = await fetchData(SYSTOPIC_ENDPOINT);
|
||||
sysTopics = await fetchData(SYSTOPIC_ENDPOINT, {
|
||||
signal: this.abort.signal,
|
||||
cache: "no-store",
|
||||
});
|
||||
this.version = sysTopics?.["$SYS/broker/version"];
|
||||
|
||||
this.previousDataFetchFailed = false;
|
||||
@@ -1492,12 +1498,16 @@ class MosquittoDashboard {
|
||||
this.setBrokerStatus();
|
||||
} catch (error) {
|
||||
const errorMsg = `Error fetching sys topics: ${error?.message}`;
|
||||
console.error(errorMsg);
|
||||
if (this.abort.signal.aborted || error?.name === "AbortError") {
|
||||
console.log("Fetching systopics aborted");
|
||||
} else {
|
||||
console.error(errorMsg);
|
||||
if (!this.previousDataFetchFailed) {
|
||||
alert(errorMsg);
|
||||
}
|
||||
}
|
||||
this.brokerOnline = false;
|
||||
this.setBrokerStatus();
|
||||
if (!this.previousDataFetchFailed) {
|
||||
alert(errorMsg);
|
||||
}
|
||||
this.previousDataFetchFailed = true;
|
||||
}
|
||||
if (!sysTopics) {
|
||||
|
||||
@@ -1,15 +1,28 @@
|
||||
class Listeners {
|
||||
constructor() {
|
||||
this.abort = new AbortController();
|
||||
registerAbortController(this.abort, this);
|
||||
this.init();
|
||||
}
|
||||
|
||||
async init() {
|
||||
try {
|
||||
const listeners = await fetchData(LISTENERS_ENDPOINT);
|
||||
const listeners = await fetchData(LISTENERS_ENDPOINT, {
|
||||
signal: this.abort.signal,
|
||||
cache: "no-store",
|
||||
});
|
||||
this.displayListeners(listeners);
|
||||
} catch (error) {
|
||||
console.error("Error fetching listeners:", error);
|
||||
alert(`Error loading listeners: ${error}`);
|
||||
if (
|
||||
this.pageHiding ||
|
||||
this.abort.signal.aborted ||
|
||||
error?.name === "AbortError"
|
||||
) {
|
||||
console.log("Fetching listeners aborted");
|
||||
} else {
|
||||
console.error("Error fetching listeners:", error);
|
||||
alert(`Error loading listeners: ${error}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,13 +19,16 @@ function toAsyncAndWaitAfter(task, delay = 0) {
|
||||
};
|
||||
}
|
||||
|
||||
async function fetchData(endpoint) {
|
||||
async function fetchData(endpoint, opts = {}) {
|
||||
if (!endpoint) {
|
||||
throw new Error("No endpoint provided to fetch data function");
|
||||
}
|
||||
|
||||
let data;
|
||||
const res = await fetch(endpoint);
|
||||
const res = await fetch(endpoint, {
|
||||
...opts,
|
||||
headers: { Accept: "application/json" },
|
||||
});
|
||||
if (res.ok) {
|
||||
data = await res.json();
|
||||
} else {
|
||||
@@ -165,3 +168,11 @@ async function copyToClipboard(textToCopy) {
|
||||
function isMobile() {
|
||||
return window.innerWidth < 1024;
|
||||
}
|
||||
|
||||
function registerAbortController(abortController) {
|
||||
// in firefox the below doesn't help unfortunately: a general netrowk error is being thrown even before the below callback is executed. A proper implementation would require aborying in-flight requets right before the navigation but it's not worth the effort. Currently you will see an alert for a quick moment when spam-clicking onto the "listern" tab in the sidebar on firefox
|
||||
const abortCallback = () => {
|
||||
abortController.abort();
|
||||
};
|
||||
window.addEventListener("pagehide", abortCallback, { once: true });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user