Soy nuevo en la programación funcional.
Como escuché muchas veces, la programación funcional podría ayudar con un mantenimiento más fácil. Por lo tanto, me gustaría ver si puede ayudar con este problema o, de hecho, es posible que deba buscar otra solución. Si se necesita otra solución, lo siento por este tema engañoso.
En mi proyecto de reacción,
Tengo dos estados, uno es Proyección, otro se llama StressProjections
Tengo una función que invocará dos llamadas Api, una vez que regrese la API. Actualizará ambos estados
A continuación se muestra mi código.
//call API1 const simulateionCall = new Promise((resolve, reject) => { axios.post < IProjectionResponse > (`/api1`, normalProjectionRequest) .then((data) => { resolve(data); }) .catch((err) => { reject(err); }); }); //call API12 const stressCall = new Promise((resolve, reject) => { axios.post < IStressProjectionResponse > (`/api2`, stressProjectionRequest) .then((data) => { resolve(data); }) .catch((err) => { reject(err); }); }); Promise.allSettled([simulateionCall, stressCall]).then((vals) => { console.log(vals); vals.forEach((val, index) => { if (val.status === "rejected") { if (index === 0) { //ERROR handling api1 props.setProjection(resMock.results); } else { //ERROR handling api22 props.setStressProjections(res.results[0].scenarios); } } else { if (index === 0) { //Set content for api 1 // @ts-ignore props.setProjection(val.value.data.result); } else { //Set content for api 2 // @ts-ignore props.setStressProjections(val.value.data.results); } } }); });Pregunta:
En mi función allsettle , como puede ver, necesito verificar con el índice antes manualmente para asignar qué función props.set y qué manejo de errores se debe llamar.
Primero 1, no es legible, ya que algunos pueden preguntarse por qué usamos esta función de configuración cuando está en el índice 0.
Second2, es difícil de mantener. Cuando se incluyen más y más llamadas Api, mi código estaría lleno de condicionales si (índice === ...) , aumenta la dificultad de lectura
Espero poder ver una nueva técnica o una forma funcional de hacer frente a los dos problemas anteriores.
Agregar un controlador como parte de la resolución ayuda a evitar las condiciones if.
const mockAxiosPost = (url, body) => { return new Promise((resolve) => { setTimeout(() => resolve(body), body.key); }); }; const normalProjectionRequest = { key: 1000, }; const stressProjectionRequest = { key: 3000, }; //call API1 const simulateionCallHandler = console.log; const simulateionCall = new Promise((resolve, reject) => { mockAxiosPost(`/api1`, normalProjectionRequest) .then((data) => { resolve({ data: data, handler: simulateionCallHandler, }); }) .catch((err) => { reject(err); }); }); //call API12 const stressCallHandler = console.log; const stressCall = new Promise((resolve, reject) => { mockAxiosPost(`/api2`, stressProjectionRequest) .then((data) => { resolve({ data: data, handler: stressCallHandler, }); }) .catch((err) => { reject(err); }); }); const props = { setProjection: console.log, setStressProjections: console.log, }; Promise.allSettled([simulateionCall, stressCall]).then((vals) => { vals.forEach((val, index) => { console.log(vals); if (val.status === 'rejected') { if (index === 0) { //ERROR handling api1 props.setProjection(resMock.results); } else { //ERROR handling api22 props.setStressProjections(res.results[0].scenarios); } } else { val.value.handler(val.value.data); } }); });evitar el antipatrón de construcción de promesa explícita
const simulateionCall = new Promise((resolve, reject) => { axios.post < IProjectionResponse > (`/api1`, normalProjectionRequest) .then((data) => { resolve(data); }) .catch((err) => { reject(err); }); });es lo mismo que -
const simulateionCall = axios.post<IProjectionResponse>("/api1", normalProjectionRequest) cometes el mismo error con stressCall .
no use Promise.allSettled
Está viendo las desventajas obvias de usar Promise.allSettled , pero no hay motivo para usarlo en primer lugar. Sus promesas pueden ejecutarse en "hilos" separados para evitar enredarlos y tener que realizar un seguimiento de sus índices.
axios .post<IProjectionResponse>("/api1", normalProjectionRequest) .then(data => props.setProjection(data.result)) .catch(console.error) // or something else axios .post<IStressProjectionResponse>("/api2", stressProjectionRequest) .then(data => props.setStressProjections(data.results)) .catch(console.error) // or something elsereaccionar
Etiquetaste esto con reaccionar. Si desea que estas dos publicaciones sucedan cuando el usuario presiona un botón:
const onClick = (event) => { axios .post<IProjectionResponse>("/api1", normalProjectionRequest) .then(data => props.setProjection(data.result)) .catch(console.error) // or something else axios .post<IStressProjectionResponse>("/api2", stressProjectionRequest) .then(data => props.setStressProjections(data.results)) .catch(console.error) // or something else } return <> ... <button type="button" onClick={onClick}>Submit</button> </> Si desea volver a ejecutar estas solicitudes de publicaciones cada vez que cambien las solicitudes normales y de proyección de estrés, use useEffect con normalProjectionRequest y stressProjectionRequest como dependencias del efecto:
useEffect(() => { axios .post<IProjectionResponse>("/api1", normalProjectionRequest) .then(data => props.setProjection(data.result)) .catch(console.error) axios .post<IStressProjectionResponse>("/api2", stressProjectionRequest) .then(data => props.setStressProjections(data.results)) .catch(console.error) }, [normalProjectionRequest, stressProjectionRequest])