class LinkChecker { static PROXY_SERVERS = [ "https://cors.eu.org/", "https://api.netnr.eu.org/link/", "https://api.codetabs.com/v1/proxy?quest=", "https://netnr.zme.ink/api/Open/Proxy?url=" ]; static proxyIndex = 0; static DEFAULT_TIMEOUT = 10000; // 10秒 static DEFAULT_CONCURRENCY = 6; static getProxyUrl(link) { const proxyServer = this.PROXY_SERVERS[this.proxyIndex++]; if (this.proxyIndex >= this.PROXY_SERVERS.length) { this.proxyIndex = 0; } return `${proxyServer}${encodeURIComponent(link)}`; } static async checkSingleLink(link, timeout = this.DEFAULT_TIMEOUT) { const url = this.getProxyUrl(link.href); try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout); const response = await fetch(url, { signal: controller.signal }); clearTimeout(timeoutId); return { link, success: response.ok }; } catch (error) { return { link, success: false }; } } static async checkLinks( links = document.links, concurrency = this.DEFAULT_CONCURRENCY, timeout = this.DEFAULT_TIMEOUT ) { const linksArray = Array.from(links); const resultOk = []; const resultBad = []; // 并发控制 let currentIndex = 0; const processNext = async () => { while (currentIndex < linksArray.length) { const index = currentIndex++; const link = linksArray[index]; try { const result = await this.checkSingleLink(link, timeout); if (result.success) { resultOk.push(result.link); } else { resultBad.push(result.link); } console.debug(`ok: ${resultOk.length}, bad: ${resultBad.length}, progress: ${index + 1}/${linksArray.length}`); } catch (error) { resultBad.push(link); console.debug(`ok: ${resultOk.length}, bad: ${resultBad.length}, progress: ${index + 1}/${linksArray.length}`); } } }; // 启动并发任务 const tasks = Array(concurrency).fill(null).map(() => processNext()); await Promise.all(tasks); // 输出结果 if (resultBad.length > 0) { console.debug('坏链接列表:'); console.debug(resultBad.map(link => link.href).join('\r\n')); } return { okLinks: resultOk, badLinks: resultBad }; } static async init(links, concurrency, timeout) { console.debug('开始检测链接...'); const result = await this.checkLinks(links, concurrency, timeout); console.debug('检测完成!'); return result; } } // 使用 LinkChecker.init();