我在做一个小的学习项目,它需要一个硬币从列表的API,然后构建一个整版引导卡为数组的长度从API接收。在开发我只用100枚第一硬币避免漫长的等待时间,但现在,当我尝试对整个3900+硬币,我完成了它需要一个不切实际长的时间。
我敢肯定,我添加了字符串的方式是问题的根源,我要添加代码,我敢肯定,它都更有意义。
我试图构建整个字符串,然后将其追加 - 没有好仍然缓慢。我试图改变它的innerHTML每一次,然后将其追加(追加里面的for循环),但它只是将覆盖所有旧的硬币,并追加只有最后一个。
我希望它做的实际上是单独追加每个箱子,做它的合理时间内,现在它接管了30分钟才能完成这显然是不好的。
我添加的代码目前的版本是一个需要很长的时间,但最终还是做对(虽然其在只有50次迭代的for循环,因此不会被卡住,如果你尝试它,现在,它需要超过3900迭代)
function homeStart(coins: any[]): void {
var divcreate = document.createElement("div");
for (var i = 0; i < 50; i++) {
// console.log(coins[i]);
// ******This is where the string addup starts
divcreate.innerHTML += `
<div class="card text-dark bg-dark m-auto makeinline"
id="${coins[i].id}${i}" style="max-width: 18rem;">
<div class="card-header">
<div class="flexalign">
<span class="coinsymbol"
id="${coins[i].symbol.toUpperCase() +
"a1"}">${coins[i].symbol.toUpperCase()}
</span>
<label class="switch">
<input type="checkbox"
id="${coins[i].id}${coins[i].symbol}"
onchange="selectedCoinUpdate(this,'${coins[i].symbol}')">
<span class="slider round"></span>
</label>
</div>
</div>
<div class="card-body">
<div class="">
<h5 class="card-title coinname">${coins[i].name}</h5>
<button type="button" class="btn btn-secondary" data-
toggle="collapse" href="#collapseIdentity${i}" role="button"
aria-expanded="false" aria-
controls="collapseIdentity${i}"
onclick="moreInfo('${coins[i].id}')">More info</button>
</div>
<div class="collapse" id="collapseIdentity${i}">
<div class="card-body" id="${coins[i].id}">
</div>
</div>
</div>
</div>`;
}
// ******This is where the string addup ends
$("#pagecont").append(divcreate);
}
对于装载DOM元素快,你可以看到这个链接 - > Memory leak in javascript, functions inside loop
把事情一样快,你能后,它仍可能太慢,并可能导致浏览器冻结/崩溃。
在JS长期运行的同步操作将锁定用户界面,。
为了防止这种情况,你可以做一个长期运行的sync
操作成async
操作,这有给UI一些喘息空间的好处。然后,您可以创建一个负载指标等。
下面是一个非常简单的例子,我在做一个同步的操作,需要100ms左右,而这样做的100倍。这则加起来一共10秒,如果你这样做,而无需使用async
它不会是一个非常好的用户体验。
为了证明UI不是关起来,我然后只闪烁负载指示粉红色的,当然你可以做一个旋转的圆圈等,它的完成后,还安慰日志all done
,..
我们希望,这个小例子将有助于长期运行sync
操作。
PS:我始终认为async/await
是为了做下一个节拍,我虽然做回路中无需sleep(0)
,仍然会造成用户界面锁定为10秒。
const loaddiv = document.querySelector(".loading");
var i = setInterval(() => {
loaddiv.classList.toggle("loading");
}, 300);
const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
async function blockUI() {
let now = new Date().getTime();
const desiredTime = now + 100;
while (now < desiredTime) {
now = new Date().getTime();
}
await sleep(0); //give the UI some breathing space
}
async function longLoop() {
for (let l = 0; l < 100; l += 1)
await blockUI();
clearInterval(i);
console.log("all done");
}
longLoop();
.loading {
background-color: pink;
}
<div class="loading">
Loading.
</div>
基思说,你可以在多任务改变你的唯一的同步操作(在他的榜样的setTimeout)运行的异步方式的任务。
这样做,而不是一个大的操作这种方式提高了UI的性能,但因为你触摸它DOM是不是很大。
触摸DOM是缓慢的,因为浏览器可能有很多业务做(油漆,回流焊等)。所以,最好是要求浏览器做你的任务时,这是对他触摸DOM和其DOM工作的最佳时机。
对于浏览器主要有两种方法,您可以使用:
所以这里有一个例子相结合的两种方法:https://codesandbox.io/s/7jz3yjow0q
正是基于此Google developer article。
这里有一些重要的资源,以了解在网络上的表现: