如何正确地优化长的for循环concats长字符串每次?

问题描述 投票:1回答:2

我在做一个小的学习项目,它需要一个硬币从列表的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);

}
javascript loops optimization append concat
2个回答
0
投票

对于装载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>

0
投票

基思说,你可以在多任务改变你的唯一的同步操作(在他的榜样的setTimeout)运行的异步方式的任务。

这样做,而不是一个大的操作这种方式提高了UI的性能,但因为你触摸它DOM是不是很大。

触摸DOM是缓慢的,因为浏览器可能有很多业务做(油漆,回流焊等)。所以,最好是要求浏览器做你的任务时,这是对他触摸DOM和其DOM工作的最佳时机。

对于浏览器主要有两种方法,您可以使用:

所以这里有一个例子相结合的两种方法:https://codesandbox.io/s/7jz3yjow0q

正是基于此Google developer article

这里有一些重要的资源,以了解在网络上的表现:

© www.soinside.com 2019 - 2024. All rights reserved.