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();
});
})
有关详细信息,请查看
我正在使用 [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();
});
})
有关详细信息,请查看