使用下面的代碼,我試圖記錄一系列回圈的進度。
但是,正如您將看到的,DOM 中并沒有順利地記錄進度。許多百分比增量被跳過。
我該如何解決?
;(async () => {
let width = document.getElementById('width')
let numOfImages = 8
let images = Array.from(Array(numOfImages).keys())
let pixelsPerImage = 3600
let totalPixels = numOfImages * pixelsPerImage
let currentLoop = 0
for (let img of images) {
await new Promise((resolve) => {
// this setTimeout is actually an image.onload callback
setTimeout(() => {
let i = 0
while (i < pixelsPerImage) {
;(function(cloop) {
window.requestAnimationFrame(() => {
let prcnt = ((100/totalPixels) * cloop).toFixed(2)
width.innerHTML = prcnt '%'
width.style.width = prcnt '%'
})
})( currentLoop)
i
}
resolve()
}, 5000)
})
}
await Promise.all(promises)
})()
https://jsfiddle.net/koyfa6pm/1/
uj5u.com熱心網友回復:
看起來您正在嘗試并行運行 8 個承諾,但它們一個接一個地運行。
它是這樣的:一個接一個地創建了 8 個承諾。每個 promise 都會注冊一個 5000 毫秒的 setTimeout。
一旦 5000 毫秒結束,將有 8 個回呼等待,運行時將一個接一個地呼叫它們(JavaScript 是單執行緒的)。
第一個 promise 將執行 3600 次回圈,并將寫入console.log3600 次。然后下一個 promise 回呼將被運行時呼叫,下一個 3600 回圈將執行相同的操作……直到所有 8 個回圈都結束。
你會看到很多,console.log因為你做了 3600*8 次……你看不到 DOM 的變化,因為瀏覽器只會在執行完成后呈現。
為了查看 dom 更改,您必須“釋放”代碼的執行,您可以這樣做setTimeout(..., 0)以獲得下一個立即渲染。甚至更好地使用requestAnimationFrame
您希望每幀都做最少的處理,以便瀏覽器快速渲染。避免巨大的回圈,緩慢的代碼。
接下來你可能會遇到的事情是進度速度根據你的 CPU 而變化,如果你想無論 CPU 功率如何都一樣,你需要開始考慮時間,這是一個完全不同的主題 :-)
uj5u.com熱心網友回復:
它減慢了整體進度,因為我現在正在等待 HTML 更新完成,然后再進入下一個回圈,但 HTML 中顯示的進度現在準確且流暢。這是一種權衡。
;(async () => {
let width = document.getElementById('width')
let topLoops = 8
let innerLoops = 3600
let totalLoops = topLoops * innerLoops
let currentLoop = 0
let images = Array.from(Array(topLoops).keys())
for (let img of images) {
await new Promise((resolve) => {
// this setTimeout is actually an image.onload callback
setTimeout(async() => {
let i = 0
while (i < innerLoops) {
currentLoop
await new Promise((resolve) => {
window.requestAnimationFrame(() => {
let prcnt = ((100/totalLoops) * currentLoop).toFixed(2)
width.innerHTML = prcnt '%'
width.style.width = prcnt '%'
resolve()
})
})
i
}
resolve()
}, 5000)
})
}
await Promise.all(promises)
})()
#width {
float:left;
height: 20px;
background: red;
color: black;
padding: 3px;
}
<div id="width"></div>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/370356.html
標籤:javascript html for循环 异步 承诺
上一篇:如何等待物件被異步編輯?
