为什么 Bootstrap Spinner 在计算密集型上下文中不可用

Why is Bootstrap Spinner Unusable in Compute Intensive Context

我知道 Javascript 是单线程的。但是我不明白为什么下面的代码没有 show/hide 微调器 before/after 计算密集型任务。

代码大纲:

showSpinner();
computeIntensiveTask();
hideSpinner();

代码(我正在使用 Bootstrap 微调器)

const showSpinner = () => {
    const $spinner = $('#spacewalk-spinner').find('.spinner-border');
    $spinner.show();
};

const hideSpinner = () => {
    const $spinner = $('#spacewalk-spinner').find('.spinner-border');
    $spinner.hide();
};

函数 computeIntensiveTask() 执行大量 sqrt() 和其他 3D 矢量数学运算。

当代码运行时,微调器永远不会出现。为什么会这样?

更新 0

作为测试,我尝试简单地更新微调器元素颜色 before/after:

之前 document.getElementById('spacewalk-spinner').style.color = 'rgb(255,0,0)';

之后 document.getElementById('spacewalk-spinner').style.color = 'rgb(0,255,0)';

并且只有 'after' 颜色发生变化。

更新 1

澄清一下。如果我删除对 hideSpinner() 的调用并将 showSpinner() 更改为 document.getElementById('spacewalk-spinner').style.display = 'block'。微调器显示 after computeIntensiveTask() 完成。尽管事实上我已将 computeIntensiveTask() 置于对 window.setTimeout 的调用中并等待 500 毫秒。

试试这个:

showSpinner();
setTimeout(() => {
    computeIntensiveTask();
    hideSpinner();
}, 300);

您需要使用 setTimeout 函数协调 UI 的更新。您还需要根据 UI 的更新定位 showSpinnerhideSpinner 函数。以这个片段为例。

const showSpinner = () => {
  const $spinner = $('#spacewalk-spinner').find('.spinner-border');
  $spinner.show();
  console.log('show');
};

const hideSpinner = () => {
  const $spinner = $('#spacewalk-spinner').find('.spinner-border');
  $spinner.hide();
  console.log('hide');
};


const computeIntensiveTask = () => {
  showSpinner();
  // begin the calculations after the UI updates by using setTimeout
  setTimeout(function() {
    for (var start = 1; start < 1000; start++) {
      // calculating...
      console.log('calc');
    }
    hideSpinner();
  }, 0);

};

computeIntensiveTask();
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="spacewalk-spinner">
  <div class="spinner-border" role="status">
    <span class="sr-only">Loading...</span>
  </div>
</div>