Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

200
Vistas
Rendimiento recursivo llamado desde setTimeout

Estoy consumiendo una API con límite de tasa, cada vez que alcanza mi límite de tasa, devuelve retry-after especificar la cantidad de segundos de espera para restablecer el límite de tasa.

Necesito:

  • Envía 100 llamadas con Promise.allSettled([...]);
  • Algunas solicitudes tendrán éxito y luego las procesarán;
  • Vuelva a intentar las solicitudes rechazadas después de los segundos especificados.

Mi solución hasta ahora:

 async *indicators(items: string[]): AsyncIterableIterator<any[]> { const res = await Promise.allSettled(items.map((item) => this.makeRequest(item))) const fulfilledRequests = res.filter((r) => r.status === 'fulfilled') as PromiseFulfilledResult<any>[] for (const { value } of fulfilledRequests) { console.log('Yielding') yield value console.log('Yielded') } const rejectedRequest = res.find((r) => r.status === 'rejected') as any const failedItems = res.filter((p) => p.status === 'rejected').map(({ reason }: any) => reason.item) if (failedItems.length === 0 || !failedItems?.reason?.retryAfter) return Logger.log(`No more items to check`) setTimeout(this.indicators(failedItems).next.bind(this), rejectedRequest.reason.retryAfter) } async makeRequest(item: string): Promise<Indicator[]> { try { const { data: { data } } = await firstValueFrom(this.httpService.post('https://api.io', { item })) return data } catch (error) { throw { retryAfter: error.response.headers['retry-after'] * 1000, symbol } } } main() { for await (const item of this.indicators(['', ''])) { console.log(item) } }
  • Las primeras iteraciones funcionan bien, de 100 elementos obtiene 30 y rinde como se esperaba;
  • Entonces setTimeout funciona como se esperaba;
  • Las funciones de los indicadores se ejecutan por segunda vez;
  • La solicitud funciona;
  • Se muestra el primer registro de Yielding y luego se detiene.

Estoy usando NestJS con Typescript en Node v16.

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

Sugeriría volver a intentar cada solicitud de forma independiente hasta que tenga éxito o abandone.

El siguiente código NO ESTÁ PROBADO

 async function main() { const promises = ["", ""].map(item=>makeRequestUntilDone(item)); const results = await Promise.allSettled(promises); for(const r of results) { if(r.status === 'fulfilled') { // process result console.log(r.value); } else { // process error if you sometimes // throw in `makeRequestUntilDone` console.log(r.reason); } } } async function makeRequestUntilDone(item: string) { while(true){ try { const { data: { data } } = await firstValueFrom(this.httpService.post('https://api.io', { item })) return data } catch (error) { // `throw error` if you don't wanna retry // anymore or it is not a retryable error, // otherwise delay and continue const retryAfter = error.response.headers['retry-after'] * 1000; await delay(retryAfter); } } } function delay(ms: number) { return new Promise(function(resolve) { setTimeout(resolve, ms); }); }

entonces tú puedes

about 4 years ago · Juan Pablo Isaza Denunciar

0

Hice que funcionara usando un ciclo do while en espera de volver a intentarlo después de un tiempo.

 async *listMeetings(meetingIds: string[]): AsyncIterableIterator<MeetingResponse> { let hasMore = false do { const res = await Promise.allSettled(meetingIds.map((id) => this.makeRequest(id))) const fulfilledRequests = res.filter((r) => r.status === 'fulfilled') for (const { value } of fulfilledRequests) { yield value } const rejectedRequest = res.find((r) => r.status === 'rejected') const failedMeetings = res.filter((p) => p.status === 'rejected').map(({ reason }: any) => reason.meetingId) if (failedMeetings.length === 0 || !rejectedRequest?.reason?.retryAfter) { hasMore = false } else { await new Promise<void>((resolve) => setTimeout(() => resolve(), rejectedRequest.reason.retryAfter)) yield* this.listMeetings(failedMeetings) } } while (hasMore) } main() { for await (const meeting of this.client.listMeetings([])) { console.log(meeting) } }
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda