@regor,
it seems there is nothing we can do on our side:
let activeRequests = [];
let isSafeToExit = false;
function checkAndExit() {
if (isSafeToExit && activeRequests.length === 0) {
fb.Exit();
} else {
setTimeout(checkAndExit, 100);
}
}
function bioOnStateChange(resolve, reject, func = null) { // credit regorxxx
if (this !== null) { // this is xmlhttp bound
if (this.Status === 200) {
return func ? func(this.ResponseText, this) : resolve(this.ResponseText);
} else if (!func) { return reject(this.ResponseText); }
} else if (!func) { return reject({ status: 408, responseText: this.ResponseText }) } // 408 Request Timeout
return null;
}
// May be used to async run a func for the response or as promise
function bioSend({ method = 'GET', URL, body = void (0), func = null, requestHeader = [], bypassCache = false, timeout = 5000 }) { // credit regorxxx
return new Promise((resolve, reject) => {
fb.RunMainMenuCommand('View/Console');
const xmlhttp = new ActiveXObject('WinHttp.WinHttpRequest.5.1');
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#bypassing_the_cache
// Add ('&' + new Date().getTime()) to URLS to avoid caching
activeRequests.push(xmlhttp); // Add to active requests list
xmlhttp.Open(method, URL + (bypassCache ? (/\\?/.test(URL) ? '&' : '?') + new Date().getTime() : ''), true);
requestHeader.forEach((pair) => {
if (!pair[0] || !pair[1]) {
console.log(`HTTP Headers missing: ${pair}`);
return;
}
xmlhttp.SetRequestHeader(...pair);
});
if (bypassCache) {
xmlhttp.SetRequestHeader('Cache-Control', 'private');
xmlhttp.SetRequestHeader('Pragma', 'no-cache');
xmlhttp.SetRequestHeader('cache', 'no-store');
xmlhttp.SetRequestHeader('If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT');
}
xmlhttp.SetTimeouts(timeout, timeout, timeout, timeout);
xmlhttp.Send(method === 'POST' ? body : void (0));
const timer = setTimeout(() => {
try {
xmlhttp.WaitForResponse(-1);
bioOnStateChange.call(xmlhttp, resolve, reject, func);
} catch (e) {
xmlhttp.Abort();
reject({ status: 408, responseText: e.message });
} finally {
clearInterval(checkResponse);
activeRequests = activeRequests.filter(req => req !== xmlhttp); // Remove from active requests
}
}, timeout);
const checkResponse = setInterval(() => {
try {
if (xmlhttp.Status && xmlhttp.ResponseText) {
clearTimeout(timer);
clearInterval(checkResponse);
bioOnStateChange.call(xmlhttp, resolve, reject, func);
activeRequests = activeRequests.filter(req => req !== xmlhttp); // Remove from active requests
}
} catch (e) {}
}, 30);
setTimeout(() => { // Simulate foobar exit during request
// Do cleanup
clearTimeout(timer);
clearInterval(checkResponse);
console.log('Aborting all active requests...');
activeRequests.forEach((request, index) => {
try {
console.log(`Aborting request ${index}`);
request.Abort();
console.log(`Request ${index} aborted successfully.`);
} catch (e) {
console.log(`Failed to abort request ${index}:`, e);
}
});
activeRequests = [];
console.log('All requests have been aborted.');
// And exit
isSafeToExit = true;
checkAndExit();
}, 500);
});
}
Log shows everything is cleared:
[2024-05-19 15:14:38.321] Aborting all active requests...
[2024-05-19 15:14:38.321] Aborting request 0
[2024-05-19 15:14:38.619] Request 0 aborted successfully.
[2024-05-19 15:14:38.619] All requests have been aborted.
[2024-05-19 15:14:38.635] Shutting down...
[2024-05-19 15:14:38.734] Unloading Script
-TT