Estoy usando [ async-mutex
]( https://github.com/DirtyHairy/async-mutex porque hay una condición de carrera en mi código debido a la devolución de solicitudes simultáneas. Y una vez que se resuelven todas las solicitudes simultáneas, cada una necesita agregar algo de la respuesta en una matriz de estado.
He incluido un codesandbox que replica este problema: https://codesandbox.io/s/runtime-haze-2407uy
También publicaré el código aquí como referencia:
import Uppy from "@uppy/core"; import XHRUpload from "@uppy/xhr-upload"; import { DragDrop, ProgressBar } from "@uppy/react"; import { Mutex } from "async-mutex"; import { useEffect, useMemo, useRef, useState } from "react"; export default function App() { const [stuff, setStuff] = useState([]); const uppy = new Uppy({ meta: { type: "file" }, autoProceed: true }); uppy.use(XHRUpload, { endpoint: `google.com/upload` }); const mutex = new Mutex(); uppy.on("upload-error", (_, response) => { mutex.acquire().then((release) => { let joined = stuff.concat("test"); setStuff(joined); console.log(stuff); release(); }); }); return ( <div className="App"> <DragDrop uppy={uppy} locale={{ strings: { // Text to show on the droppable area. // `%{browse}` is replaced with a link that opens the system file selection dialog. dropHereOr: "Drop here or %{browse}", // Used as the label for the link that opens the system file selection dialog. browse: "browse" } }} /> </div> ); }
Espero que, al cargar dos archivos (el servidor de carga es falso, pero eso es lo que se pretende, porque todas las solicitudes (una por archivo) desencadenarán el evento upload-error
) que la matriz de stuff
terminará como ['test', 'test']
. Sin embargo, eso no sucede:
La razón de esto es porque el "estado" (sin juego de palabras) del estado de stuff
es incierto en el momento de ejecutar setState
, debido a que la naturaleza de setStuff
y los establecedores de estado en general son asincrónicos.
La solución es
a) use await
porque en cualquier caso la adquisición de bloqueo mutex es una promesa
b) pasar una función lambda a setStuff
que garantice que el estado de las stuff
estará actualizado, en lugar de simplemente asumir que las stuff
estarán actualizadas (que no lo estarán)
uppy.on('upload-error', async (_, response) => { await mutex.acquire().then((release) => { setStuff((prevState => { return prevState.concat('test'); })); release(); }); })
Para obtener más información, consulte https://stackoverflow.com/a/44726537/8652920