Tengo una aplicación Vue3 en la que utilizo el siguiente enfoque para las llamadas a la API:
api , dentro de la cual se encuentran funciones que directamente hacen una llamada al backend. Por ejemplo: export async function getCourses(): Promise<Course[]> { const response = await axios.get(`/courses/`); return response.data; } export async function getCourse(courseId: string): Promise<Course> { const response = await axios.get(`/courses/${courseId}/`); return response.data } export async function getExercises(courseId: string): Promise<Exercise[]> { const response = await axios.get(`/courses/${courseId}/exercises/`); return response.data } hay una tienda Vuex, cuyas acciones invocan esas funciones en las carpetas api y envían datos al estado de la tienda
Los componentes de Vue acceden al estado de la tienda y le envían acciones para recuperar datos
El problema que tengo con este enfoque es que las funciones de api se vuelven extremadamente repetitivas. Tengo que definir 4 funciones diferentes solo para habilitar CRUD en una entidad, y todas toman casi los mismos parámetros (por ejemplo, en mi aplicación, todos los recursos son subrecursos de un curso y, por lo tanto, requieren el parámetro de courseId de curso para obtener) y tener la misma estructura (esperar una llamada axios y devolver los data de la respuesta).
Preferiría un método en el que defina de forma declarativa las rutas y los parámetros que esperan (en lo que respecta a los componentes de URL, como los ID), y luego poder escribir de forma segura hacer algo como esto:
getApiService().courses(courseId).delete() // deletes a course getApiService().courses(courseId).exercises().get(exerciseId) // returns an exercise getApiService().courses(courseId).exercises().post(payload) // creates and returns an exercise getApiService().courses(courseId).exercises().get(exerciseId).choices().list() // returns the list of choices for an exercise // and so on¿Cuál sería una buena manera de lograr esto? ¿Hay algún paquete existente que haga esto para Vue3?
El código actual es limpio y razonablemente HÚMEDO, lo que hace que sea mucho más fácil de mantener que las posibles soluciones DRY. Los peligros de los enfoques DRY entusiastas se tratan en esta charla popular y se explican en este artículo.
Si se sabe que estas funciones siempre devuelven data sin transformar, podrían reemplazarse con alguna función auxiliar de DRYer:
const apiCall = <T extends any>(url: string, options?: AxiosRequestConfig<T>): Promise<T> => { const response = await axios<T>(url, options); return response.data }Pasar el método HTTP a través de las opciones lo hace más flexible de usar.