我想在函式執行期間顯示影片 GIF(微調器圖示),然后在函式完成時隱藏 GIF。
但是,我正在實作的代碼顯然沒有顯示 GIF,因為該函式占用了執行緒并且不允許顯示 GIF。
示例:(https://jsfiddle.net/jzxu8cLt/)
HTML
<button onclick="go();">Go</button>
<span id="result"></span>
<hr>
<img style="display: none;" id="spinner" src="https://upload.wikimedia.org/wikipedia/commons/b/b1/Loading_icon.gif">
JS
function longLoop() {
let count = 1000000000;
let result = 0;
for (let i = 1; i <= count; i ) {
result = i;
}
return result;
}
function go() {
let spinnerElement = document.getElementById('spinner');
let resultElement = document.getElementById('result');
spinnerElement.style.display = 'block';
let result = longLoop();
resultElement.innerHTML = result;
spinnerElement.style.display = 'none';
}
上面的 go() 函式應該在呼叫長時間運行的函式之前完成顯示 GIF 的作業,然后在長時間運行的函式完成時隱藏 GIF。
但是,GIF 從來沒有機會在瀏覽器中顯示,我不知道如何讓 GIF 顯示。注意:如果我在呼叫 longLoop() 函式的行放置斷點,GIF 將正確顯示。
在 longLoop() 函式期間,我需要做什么才能讓 GIF 顯示和影片?
uj5u.com熱心網友回復:
在setTimeout中運行長時間運行并恢復代碼,省略計時引數,或者0將“立即”執行,或者更準確地說,在下一個事件周期執行,這將防止阻塞。
function longLoop() {
let count = 1000000000;
let result = 0;
for (let i = 1; i <= count; i ) {
result = i;
}
return result;
}
function go() {
let spinnerElement = document.getElementById('spinner');
let resultElement = document.getElementById('result');
spinnerElement.style.display = 'block';
setTimeout(() => {
let result = longLoop();
resultElement.innerHTML = result;
spinnerElement.style.display = 'none';
})
}
<button onclick="go();">Go</button>
<span id="result"></span>
<hr>
<img style="display: none;" id="spinner" src="https://upload.wikimedia.org/wikipedia/commons/b/b1/Loading_icon.gif">
uj5u.com熱心網友回復:
我會為你推薦使用 async/await ,pourpuse 將是更易讀的代碼,這里有一個解決方案:
function longLoop(timeout) {
return new Promise(resolve => setTimeout(resolve, timeout));
}
async function go() {
let spinnerElement = document.getElementById('spinner');
let resultElement = document.getElementById('result');
spinnerElement.style.display = 'block';
let result = await longLoop(4000);
spinnerElement.style.display = 'none';
}
uj5u.com熱心網友回復:
是的,你是對的,因為 JavaScript 是單執行緒的,longLoop 函式會阻塞事件回圈并且不給瀏覽器渲染 gif 的機會。
JsFiddle 解決方案:https ://jsfiddle.net/12yf4tgd/
我使用 setTimeout 使 longLoop 函式異步并將其包裝在 Promise 中,以便其他分配在它完成后運行。
function go() {
let spinnerElement = document.getElementById('spinner');
let resultElement = document.getElementById('result');
spinnerElement.style.display = 'block';
new Promise(resolve => setTimeout(() => {
resolve(longLoop())
}))
.then((result) => {
spinnerElement.style.display = 'none';
resultElement.innerHTML = result;
})
}
由于它是由一些 Web Api 在其他地方而不是在主呼叫堆疊上處理的,因此它不會阻塞。
如果你不想使用 .then() 因為所有的嵌套,另一個選擇是讓 go() 和 async 函式利用 async/await 語法。
async function go() {
let spinnerElement = document.getElementById('spinner');
let resultElement = document.getElementById('result');
spinnerElement.style.display = 'block';
let result = await new Promise((resolve, reject) => {
setTimeout(() => resolve(longLoop()))
})
spinnerElement.style.display = 'none';
resultElement.innerHTML = result;
}
它們都以相同的方式作業。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/459208.html
標籤:javascript 非阻塞 动画-gif
上一篇:過濾來自json物件的值范圍
下一篇:如何加快熊貓回圈?
