Necesito un método recursivo para acumular todos los resultados de una serie de llamadas paginadas y devuelve la lista completa de resultados. Algo se siente mal en la forma en que lo estoy haciendo y siento que hay una mejor manera de hacerlo, posiblemente con Array.reduce
Cualquier recomendación apreciada.
interface Result { users: Widget[]; start: number; } interface Widget { id: number; } // create 3 widgets for test const widgets = Array(3).fill(null).map((i, index: number) => { return { id: index + 1, } as Widget; }); const getFromAPI = (start: number = 0): Result => { // return 1 at a time from a specified position const current = widgets.slice(start, start + 1); let nextStart: number | undefined; if (start < widgets.length - 1) { nextStart = start + 1; } return { users: current, start: nextStart, } } // I don't like that em is outside the scope here let em: Widget[] = []; const getWidgets = (start?: number): Widget[] => { const result = getFromAPI(start); em = [...em, ...result.users]; if (result.start) { getWidgets(result.start); } return em; } const all = getWidgets();No le gusta que em esté fuera del alcance de getWidget() y que lo esté reasignando dentro del cuerpo de la función y, por lo tanto, dependa de los efectos secundarios . En cambio, parece que quieres algo más puramente funcional , sin depender de los cambios de estado.
Si es así, entonces un enfoque que puede tomar es convertir em otro argumento para la función, y tenerlo inicialmente vacío, y luego devolver el resultado recursivo de getWidgets() llamado con la próxima versión de em :
const getWidgets = (em: Widget[] = [], start?: number): Widget[] => { const result = getFromAPI(start); const nextEm = [...em, ...result.users]; return result.start ? getWidgets(nextEm, result.start) : nextEm; } Cambié la reasignación de em a una nueva variable nextEm en caso de que desee evitar efectos secundarios incluso dentro del cuerpo de getWidgets también. Hace que el algoritmo sea un poco más claro de todos modos.
Puede verificar que una llamada a getWidgets() produce el mismo resultado que en su ejemplo:
const all = getWidgets(); console.log(all); // [{ "id": 1}, { "id": 2}, { "id": 3}]