如何等待 3 个异步函数完成反应?

How to wait for 3 async functions to finish in react?

我正在使用以下库生成 sha256 哈希值:

https://www.npmjs.com/package/crypto-hash

哈希正在运行,但它是异步的。我想弄清楚如何等待以下代码执行:

async function hashAnswers() {
    try {
      await sha256(firstAnswer)
        .then(hash => { setFirstHash(hash)})
      await sha256(secondAnswer)
        .then(hash => { setSecondHash(hash)})
      await sha256(thirdAnswer)
        .then(hash => { setThirdHash(hash)})
    }
    catch (error) {
      console.log(error);
    }
  }

并在这里调用它:

 async function handleSubmit() {
    await hashAnswers().then(result => {
      console.log(firstHash);
    })
  }

但是,它不会在记录之前等待散列的答案。

提前致谢

如果您使用 then,则无需 await。我不确定 setFirstHashsetSecondHash return 是什么,但看起来 Promise.all 可能会按照 Brian 的建议为您完成这项工作。这是要点:

const hashAnswers = () => {
    const promises = [];
        try {
            promises.push(
                sha256(firstAnswer).then(hash => {
                    setFirstHash(hash);
                    return 'first is set';
                })  
            );
            
            promises.push(
                sha256(secondAnswer).then(hash => {
                    setSecondHash(hash);
                    return 'second is set'
                })
            );
            /*
            ... More push() calls ...
             */
            
            return promises;
        }
        catch (error) {
            console.log(error);
            return [];
        }       
}

const handleSubmit = () => {
    Promise.all(hashAnswers())
        .then(result => {
            console.log(result);
        })
}

请注意,如果出现错误,hashAnswers return 是一个空数组,以便 Promise.all 可以解析,但您将通过 [=18= 看到错误消息]

编辑:

评论中提出的解决方案使用Promise.all其实是一个很好的建议。你只需要让你的 hashAnswers 函数 return 一个值的元组,这些值是答​​案的散列:

async function hashAnswers() {
    return Promise.all([
        sha256(firstAnswer), sha256(secondAnswer), sha256(thirdAnswer),
    ]).catch(error => {
       console.log(error);
       return [null, null, null];
    });
}

现在您的 handleSubmit 函数将可以访问值 returned:

async function handleSubmit() {
    const [hash1, hash2, hash3] = await hashAnswers();
    setFirstHash(hash1);
    setSecondHash(hash2);
    setThirdHash(hash3);
    
    console.log(hash1);
}

上一个回答:

第一个问题是在react中,setState是异步的,不会立即更新状态。因此,您对 setXHash 等的所有调用可能不会在您准备好使用它们之前实际更新状态。

第二个问题是您的函数将无法访问更新的值,因为它们将在组件的不同渲染中更新,这将不同于调用函数的当前渲染。请记住,每次状态更改都会导致整个组件 re-render.

解决方案?

有两种可能的解决方案:

  • 创建另一个在函数完成时更新的状态
  • 将哈希存储在可变引用中 (useRef)

第二个选项可能最容易实施:

const firstHashRef = useRef();
// Do the same for secondHashRef, etc
...
async function hashAnswers() {
    try {
      await sha256(firstAnswer)
        .then(hash => { firstHashRef.current = hash; })
      await sha256(secondAnswer)
        .then(hash => { secondHashRef.current = hash; })
      await sha256(thirdAnswer)
        .then(hash => { thirdHashRef.current = hash; })
    }
    catch (error) {
      console.log(error);
    }
}

现在在您的 handleSubmit 函数中,您可以在异步 hashAnswers 完成后 console.log(firstHashRef.current)