当显示 window 提示符时,`setInterval` 在 React Component 效果挂钩中暂停

`setInterval` gets paused in React Component effect hook when window prompter is shown

const TestComponent: React.FC = (props) => {
  const [count, setCount] = useState(100);
  useEffect(() => {
    const interval = setInterval(() => {
      if (count === 98) {
        prompt("helloworld?");
        clearInterval(interval);
      }
      setCount((count: number) => count - 1);
    }, 1000);
    return () => {
      clearInterval(interval);
    };
  }, [count]);

  return <div>{count}</div>;
};

这是我的示例代码。

我希望间隔函数保持 运行 无论是否显示提示符。

但是正如问题所说,组件暂停并且计时器停止,直到用户输入解决提示符。

有没有办法既保持间隔运行又让组件保持呈现新状态?

更深入一点,我也很好奇是什么导致了这种行为。

我猜它来自一些相关的东西 single threaded aspect of javascript 但正如我所说,这只是猜测。

规范规定 prompt 在等待用户响应时必须暂停:

https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-prompt-dev

The prompt(message, default) method steps are:

...

  1. Pause while waiting for the user's response.

https://html.spec.whatwg.org/multipage/webappapis.html#pause

While a user agent has a paused task, the corresponding event loop must not run further tasks, and any script in the currently running task must block. User agents should remain responsive to user input while paused, however, albeit in a reduced capacity since the event loop will not be doing anything.

我认为您可以使用 iframe 来绕过它,但显然即使这样也行不通:

window.onmessage = function(e) {
        console.log('done');
};

setInterval(() => console.log('waiting'), 1000)
<iframe style="height:0; width: 0; display: none" id="demo"
        srcdoc="<script>window.parent.postMessage(prompt('hello'), '*')</script>">
        
</iframe>

这意味着,您 唯一 绕过它的方法实际上是伪造一个提示,例如 Creating a suitable replacement for prompt