Javascript async-mutex 似乎没有正确锁定

Javascript async-mutex does not seem to lock properly

我正在使用 [async-mutex](https://github.com/DirtyHairy/async-mutex 因为我的代码中存在来自并发请求返回的竞争条件。并且在所有并发请求解决后,它们每个都需要添加一些东西从响应到状态数组。

我已经包含了一个复制这个问题的codesandbox:https://codesandbox.io/s/runtime-haze-2407uy

我也会post这里的代码供参考:

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>
  );
}

我预计,当上传两个文件时(上传服务器是假的,但这是有意的,因为所有请求(每个文件一个)都会触发 upload-error 事件),stuff 数组将最终像 ['test', 'test']。然而,这并没有发生:

这是因为 stuff 状态的“状态”(没有双关语意)在 运行 setState 时是不确定的,由于setStuff 和状态设置器通常是异步的。

解决方法是

a) 使用 await 因为在任何情况下互斥锁获取都是一个承诺

b) 将 lambda 函数传递给 setStuff 以保证 stuff 的状态将是最新的,而不是仅仅假设 stuff 将是最新的(这不会的)

    uppy.on('upload-error',  async (_, response) => {
        await mutex.acquire().then((release) => {
            setStuff((prevState => {
                return prevState.concat('test');
            }));
            release();
        });
    })

有关详细信息,请查看