Reintentos con backoff en JavaScript
Volver a intentar, esperando más cada vez, y rendirse en algún momento.
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function retry(work, { attempts = 4, base = 5 } = {}) {
let lastError;
for (let attempt = 1; attempt <= attempts; attempt += 1) {
try {
return await work(attempt);
} catch (error) {
lastError = error;
if (attempt === attempts) break;
await sleep(base * 2 ** (attempt - 1));
}
}
throw new Error(`failed after ${attempts} attempts`, { cause: lastError });
}
async function main() {
const value = await retry(async (attempt) => {
if (attempt < 3) throw new Error(`attempt ${attempt} failed`);
return "succeeded";
});
console.log(value);
const failed = await retry(async () => {
throw new Error("always");
}, { attempts: 2 }).catch((e) => e);
console.log(failed.message, "|", failed.cause.message);
}
main();
Cómo funciona
- La espera se duplica; eso es lo que significa backoff.
- Reintenta solo lo que valga la pena reintentar.
- Adjunta el último error como causa al rendirte.
Palabras clave y builtins usados aquí
Promiseasyncawaitbreakcatchconstforfunctionifletreturnthrowtry
El intento, en números
- Líneas
- 30
- Caracteres a escribir
- 787
- Tokens
- 232
- Ritmo de tres estrellas
- 110 tpm
Al ritmo de tres estrellas de 110 tokens por minuto, este intento toma unos 127 segundos.
Paso 3 de 4 en Cancelar y limitar; paso 17 de 19 en Promesas y async.