diff --git a/components/utils/jsping.js b/components/utils/jsping.js deleted file mode 100644 index 8a824ce..0000000 --- a/components/utils/jsping.js +++ /dev/null @@ -1,38 +0,0 @@ -function request_image(url) { - return new Promise(function(resolve, reject) { - var img = new Image(); - var settled = false; - function settleOk() { - if (settled) return; - settled = true; - clearTimeout(failTimer); - img.onload = img.onerror = null; - resolve(img); - } - function settleFail() { - if (settled) return; - settled = true; - clearTimeout(failTimer); - img.onload = img.onerror = null; - reject(url); - } - img.onload = settleOk; - img.onerror = settleFail; - img.src = url + '?random-no-cache=' + Math.floor((1 + Math.random()) * 0x10000).toString(16); - var failTimer = setTimeout(settleFail, 5000); - }); -} - -function ping(url, multiplier) { - return new Promise(function(resolve, reject) { - var start = (new Date()).getTime(); - var response = function() { - var delta = ((new Date()).getTime() - start); - delta *= (multiplier || 1); - resolve(delta); - }; - request_image(url).then(response).catch(response); - }); -} - -export default ping; diff --git a/components/utils/jsping.ts b/components/utils/jsping.ts new file mode 100644 index 0000000..9925957 --- /dev/null +++ b/components/utils/jsping.ts @@ -0,0 +1,30 @@ +async function ping(url: string, multiplier = 1, signal?: AbortSignal): Promise { + const address = url.trim(); + const target = new URL(/^[a-z][a-z\d+.-]*:\/\//i.test(address) ? address : `http://${address}`); + if (target.protocol !== 'http:' && target.protocol !== 'https:') { + throw new Error('Server addresses must use HTTP or HTTPS.'); + } + + const controller = new AbortController(); + const abort = () => controller.abort(); + if (signal?.aborted) abort(); + signal?.addEventListener('abort', abort, { once: true }); + const timeout = setTimeout(abort, 5000); + const start = performance.now(); + + try { + await fetch(target.href, { + method: 'HEAD', + mode: 'no-cors', + cache: 'no-store', + credentials: 'omit', + signal: controller.signal, + }); + return (performance.now() - start) * multiplier; + } finally { + clearTimeout(timeout); + signal?.removeEventListener('abort', abort); + } +} + +export default ping;