javascript 使用setTimeout返回递归调用

sz81bmfz  于 2023-02-15  发布在  Java
关注(0)|答案(2)|浏览(108)

我正在调用智能合约函数来获取一些状态,这与调用API相同。而且,我需要在将其返回到前端之前检查是否为status.fulfilled===true。为此,我需要每秒调用一次API以尽快返回结果。通常需要5-20秒才能完成。
下面是我如何尝试做到这一点:

async function getStatus(requestId) {
    try {
      await Moralis.enableWeb3({ provider: 'metamask' });
      const options = {
        contractAddress: coinFlipAddress,
        functionName: 'getStatus',
        abi: coinFlipABI,
        params: { requestId },
      };
      var status = await Moralis.executeFunction(options);
      console.log(status);
      if (status.fulfilled) {
        console.log('fulfilled');
        return status;
      } else {
        setTimeout(async () => {
          return await getStatus(requestId);
        }, 1000);
      }
    } catch (err) {
      console.log(err);
      return { error: err };
    }
  }

这会不断递归调用getStatus函数,直到status.fulfilled===trueconsole.log('fulfilled');也记录了它的执行时间,但它不会将它返回到它第一次初始化的位置。

const handleFlip = async (choice) => {
    setCurrentChoice(null);
    setMetamaskInProgress(true);
    const transaction = await flip(choice, amount);
    setMetamaskInProgress(false);
    setCurrentChoice(choices[choice]);
    setFlipping(true);
    setResult('Spinning');
    const requestId = waitForConfirmation(transaction);
    const result = await getStatus(requestId); //This is the initial call to getStatus()
    console.log('RESULT ' + result);
    if (result) {
      setFlipping(false);
      setSide(result.hasWon ? (choice === '0' ? 'Heads' : 'Tails') : choice === '0' ? 'Tails' : 'Heads');
      setResult(result.hasWon ? 'You have won!' : 'You have lost :(');
    }
  };

我做错了什么?还有,递归调用会不会给内存带来问题?如果是,你有什么建议来处理这种情况吗?

q1qsirdb

q1qsirdb1#

不能从setTimeout回调执行return。您需要执行promisify that,等待,然后返回:

async function getStatus(requestId) {
  try {
    await Moralis.enableWeb3({ provider: 'metamask' });
    const options = {
      contractAddress: coinFlipAddress,
      functionName: 'getStatus',
      abi: coinFlipABI,
      params: { requestId },
    };
    var status = await Moralis.executeFunction(options);
    console.log(status);
    if (status.fulfilled) {
      console.log('fulfilled');
      return status;
    } else {
      await new Promise(resolve => {
        setTimeout(resolve, 1000);
      });
      return getStatus(requestId);
    }
  } catch (err) {
    console.log(err);
    return { error: err };
  }
}
lnlaulya

lnlaulya2#

您可以根据需要尝试更改maxRetry和spaceBetweenRetry

async function getStatus(requestId) {
    return new Promise(async (resolve, reject) => {
    try {
      let maxRetry = 10; //how many times you want to retry
      let spaceBetweenRetry = 1000; // sleep between retries in ms
      await Moralis.enableWeb3({ provider: 'metamask' }); //Guessing you need to call this only once
      const options = {
        contractAddress: coinFlipAddress,
        functionName: 'getStatus',
        abi: coinFlipABI,
        params: { requestId },
      };
      for (let index = 0; index < maxRetry; index++) {
        var status = await Moralis.executeFunction(options); // check status
        console.log(status);
        if (status.fulfilled) {
          resolve(status) //return the promise if fullfilled.
        }
        await new Promise((r) => setTimeout(r, spaceBetweenRetry)); // sleep for spaceBetweenRetry ms
      }
    } catch (err) {
      reject(err)
    }
  })}

相关问题