/
doremi
/
tat-dvor
Обзор
Документация
Войти
/
doremi
/
tat-dvor
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/http.mjs
74 строки
2 KB
doremi
Create project
01 авг 2026, 18:45
01 авг 2026, 18:45
f2ee3ce
Код
Авторство
О чём код?
const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'; const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); export async function fetchWithRetry(url, { retries = 4, timeoutMs = 120000, ...init } = {}) { let lastError; for (let attempt = 0; attempt <= retries; attempt++) { if (attempt > 0) await sleep(Math.min(500 * 2 ** (attempt - 1), 8000)); const ac = new AbortController(); const timer = setTimeout(() => ac.abort(), timeoutMs); try { const res = await fetch(url, { ...init, signal: ac.signal, headers: { 'User-Agent': UA, ...init.headers }, }); if (res.status >= 500 || res.status === 429) { lastError = new Error(`HTTP ${res.status}`); continue; } return res; } catch (e) { lastError = e; } finally { clearTimeout(timer); } } throw lastError; } export async function runPool(items, concurrency, worker) { const results = new Array(items.length); let next = 0; const runners = Array.from({ length: Math.min(concurrency, items.length) }, async () => { while (true) { const i = next++; if (i >= items.length) return; results[i] = await worker(items[i], i); } }); await Promise.all(runners); return results; } export class Progress { constructor(total, label) { this.total = total; this.label = label; this.done = 0; this.startedAt = Date.now(); this.lastPrint = 0; } tick(suffix = '') { this.done++; const now = Date.now(); if (now - this.lastPrint < 500 && this.done < this.total) return; this.lastPrint = now; const elapsed = (now - this.startedAt) / 1000; const rate = this.done / Math.max(elapsed, 0.001); const eta = rate > 0 ? Math.round((this.total - this.done) / rate) : 0; const line = `${this.label}: ${this.done}/${this.total} (${((this.done / this.total) * 100).toFixed(1)}%) ` + `${rate.toFixed(1)}/s ETA ${fmtDuration(eta)} ${suffix}`; process.stdout.write('\r' + line.padEnd(120).slice(0, 120)); if (this.done >= this.total) process.stdout.write('\n'); } } export function fmtDuration(seconds) { const s = Math.max(0, Math.round(seconds)); const h = Math.floor(s / 3600); const m = Math.floor((s % 3600) / 60); return h > 0 ? `${h}ч${String(m).padStart(2, '0')}м` : `${m}м${String(s % 60).padStart(2, '0')}с`; }