You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中Spinner配合循环计算无法正常工作问题求助

React Native加载指示器(Spinner)不显示问题

我用React Native开发应用,现在实现Spinner功能时遇到问题。我有个calculatorLoops函数,里面是嵌套循环做数值计算,需求是计算过程中显示Spinner,循环结束后隐藏。但把函数设为async后达不到预期效果,加了await fetch("https://www.google.com/")后Spinner能正常显示,用Promise替代fetch却没用,而且我根本不需要这个fetch请求。

相关代码:

const calculatorLoops = async (column: string) => {
  await fetch("https://www.google.com/");
  let howManyLoop = 0;
  let isWon = false;
  let founds;

  while (!isWon) {
    founds = compareNumbers(user.lotteryNumbers[column], { lotteryNumbers: createNumbers() });

    howManyLoop++;
    if (founds.cnt === loopNum) isWon = true;
  }
  setFoundNum({ foundCnt: howManyLoop, foundNumbers: founds.foundsNumbers });
};


const handlePress = async (column: string) => {
  setLoading(true);
  await calculatorLoops(column);
  setLoading(false);
};


// 尝试用Promise的版本
const calculatorLoops = async (column: string) => {
  return new Promise((res, rej) => {
    let howManyLoop = 0;
    let isWon = false;
    let founds;

    while (!isWon) {
      founds = compareNumbers(user.lotteryNumbers[column], { lotteryNumbers: createNumbers() });

      howManyLoop++;
      if (founds.cnt === loopNum) isWon = true;
    }
    res(setFoundNum({ foundCnt: howManyLoop, foundNumbers: founds.foundsNumbers }));
  });
};

问题原因

JavaScript是单线程的,你的循环计算是同步阻塞操作——就算包在Promise里,整个循环还是会一次性占满主线程,根本没给React更新UI(显示Spinner)的机会。而fetch是异步网络请求,会把线程交还给React,让UI有时间更新,之后才执行后续的循环。

解决方案

要把同步计算拆成小块,让主线程有间隙处理UI更新。可以用setTimeout或者requestAnimationFrame把循环的每一步(或每几步)放到下一个事件循环里执行。

修改后的代码示例

const calculatorLoops = async (column: string) => {
  let howManyLoop = 0;
  let isWon = false;
  let founds;

  // 封装单次计算为异步步骤
  const loopStep = () => {
    return new Promise(resolve => {
      // 用setTimeout让出主线程,给UI更新留时间
      setTimeout(() => {
        founds = compareNumbers(user.lotteryNumbers[column], { lotteryNumbers: createNumbers() });
        howManyLoop++;
        isWon = founds.cnt === loopNum;
        resolve(isWon);
      }, 0);
    });
  };

  // 异步循环,每次await后让出线程
  while (!isWon) {
    await loopStep();
  }

  setFoundNum({ foundCnt: howManyLoop, foundNumbers: founds.foundsNumbers });
};

const handlePress = async (column: string) => {
  setLoading(true);
  await calculatorLoops(column);
  setLoading(false);
};

优化建议

  • 如果单次计算很快,可以一次处理多步循环(比如一次跑50次计算再await),这样既保证UI响应,又不会因为频繁切换线程拖慢计算速度:
    const loopStep = () => {
      return new Promise(resolve => {
        setTimeout(() => {
          // 一次跑50次计算
          for (let i = 0; i < 50; i++) {
            if (isWon) break;
            founds = compareNumbers(user.lotteryNumbers[column], { lotteryNumbers: createNumbers() });
            howManyLoop++;
            isWon = founds.cnt === loopNum;
          }
          resolve(isWon);
        }, 0);
      });
    };
    

内容的提问来源于stack exchange,提问作者Lior98

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 00:54:58