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

Given Two async functions, which function runs first?

const [counter, setCounter] = useState(0)

假设我有两个异步函数 func1 和 func2。 这两个函数都是异步的并更新计数器状态。 func1 运行s 在 func2.

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

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

func1()
func2()

问题:

  1. 是否保证func2的useState 运行s时,Counter的状态由func1更新? 请记住这两个函数都是异步的。
  2. 如果不是,我应该怎么做才能确保 func2 仅在 func1 的 Usestate 更新了 Counter 的值后才使用 State 运行s。

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

Is it guaranteed that when func2's useState runs, the Counter's state is updated by func1?

不,一点也不。

If not, what should I do to make sure that func2's use State runs only after func1's Usestate has updated the Counter's value.

您可以让 func2 等到 func1 编辑的承诺 return 解决(async 总是 return 承诺), 但是 这并不一定意味着 func2setCounter 状态更新发生之前没有开始 运行;状态更新也是异步的。

为了确保这一点,您需要等待 func1 的承诺来解决 使用 [=23= 的 callback form ]: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 的回调形式。关闭状态变量的陈旧副本真的很容易;使用回调形式可确保您使用的是 up-to-date 状态。

不,肯定不能保证当func2运行sfunc1已经更新了状态。您可以使用功能组件实现这一点,方法是使用 useEffect 挂钩来跟踪状态 counter:

的变化
useEffect(() => {
 func2();
}, [counter])

通过这样做,每次计数器状态发生变化时,您都会 运行ning func2。此外,如果您想确保 func2func1 更新状态后仅获得一次 运行 ,您可以使用类似的标志这个:

const isStateUpdatedByFunc1 = useRef(false);

async function func1() {
    ....extra code
    isStateUpdatedByFunc1.current = true;
    setCounter(counter + 1);
}

useEffect(() => {
 if(isStateUpdatedByFunc1.current){
  isStateUpdatedByFunc1.current = false;
  func2();
 }
}, [counter])