为什么 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 的更新定位 showSpinner
和 hideSpinner
函数。以这个片段为例。
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>
我知道 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 的更新定位 showSpinner
和 hideSpinner
函数。以这个片段为例。
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>