给定两个异步函数,哪个函数先运行?


const [counter, setCounter] = useState(0)

假设有两个异步函数func1和func2。这两个函数都是异步的,并更新计数器状态。Func1运行在func2之前

async function func1() {
....extra code
setCounter(counter + 1)
}
async function func2() {
....extra code
setCounter(counter + 1)
}
func1()
func2()

问题:

  1. 是否保证当func2的useState运行时,计数器的状态由func1更新?请记住这两个函数都是异步的。
  2. 如果没有,我应该做些什么来确保func2的use State只在func1的Usestate更新了Counter的值之后才运行。

在这里,func1和func2的使用状态都是将Counter加1。不管哪个函数先运行,输出都是一样的。但是,在回答"请回答"时,就好像两种状态执行不同的任务,为了达到预期的结果,func1应该在func2之前运行。

是否保证当func2useState运行时,计数器的状态由func1更新?

不,一点也不。

如果没有,我应该做些什么来确保func2的使用状态只在func1Usestate更新了计数器的值之后才运行。

你可以让func2等待直到func1返回的承诺(async函数总是返回一个承诺),但是这并不一定意味着func2setCounter状态更新发生之前没有开始运行;状态更新也是异步的。

为了确保这一点,您需要同时等待func1的承诺来解决。使用setCounter:setCounter(c => c + 1): 的回调形式
async function func1() {
// ....extra code
setCounter(counter + 1);
}
async function func2() {
// ....extra code
setCounter(c => c + 1); // Note the callback form of state setter
}
func1().then(() => func2);

有很多种旋转方式。例如,您可以将func1的promise作为参数传递给func2,并在最后只设置await:

基本思想是让func2等待直到func1完成。

async function func1() {
// ....extra code
setCounter(counter + 1);
}
async function func2(promise) {
// ....extra code
await promise;          // Wait for `func1` to finish
setCounter(c => c + 1); // Note the callback form of state setter
}
func2(func1());

在绝大多数情况下,你可能并不关心func1是否完成;只要在两个地方使用setCounter的回调形式,这样它们都不会使用过时状态(它们关闭的counter):

async function func1() {
// ....extra code
setCounter(c => c + 1);
}
async function func2() {
// ....extra code
setCounter(c => c + 1);
}
func1();
func2();

事实上,我认为任何当您使用现有状态(counter的前一个值)来更新状态(将其加1)时,您应该使用setter的回调形式。关闭状态变量的旧副本真的很容易;使用回调表单可以确保您使用的是最新状态。

不能保证当func2运行时func1已经更新了状态。要在功能组件中实现这一点,你可以使用useEffect钩子来跟踪状态计数器:

的变化。
useEffect(() => {
func2();
}, [counter])
通过这样做,每次计数器状态发生变化时都运行func2。另外,如果您想确保func1更新状态后func2只运行一次,您可以使用这样的标志:
const isStateUpdatedByFunc1 = useRef(false);
async function func1() {
....extra code
isStateUpdatedByFunc1.current = true;
setCounter(counter + 1);
}
useEffect(() => {
if(isStateUpdatedByFunc1.current){
isStateUpdatedByFunc1.current = false;
func2();
}
}, [counter])

最新更新