type Task = () => Promise; class SerialQueue { private chain: Promise = Promise.resolve(); run(task: Task, retries = 1): Promise { const attempt = async (remaining: number): Promise => { try { return await task(); } catch (err) { if (remaining > 0) { await new Promise((r) => setTimeout(r, 1500)); return attempt(remaining - 1); } throw err; } }; const result = this.chain.then(() => attempt(retries)); this.chain = result.catch(() => {}); // keep the chain alive even after a failure return result; } } export const crawlQueue = new SerialQueue();