使用 ajax 更新元素不影响直到 for 循环结束

Update element with ajax don't affect until for loop end

我想用 AJAX 一个接一个地打印很多数字。

像这样:(每一行都是前一行的更新!)

output is:
    1
    12
    123
    1234
    12345
    123456
    ...

我尝试了很多并阅读了很多相同的问题,但我找不到正确的答案。

真正的问题是 javascript 中的每个 FOR 循环在结束循环后都不会影响 DOM。我只想在处理较长的 运行 作业时更新 FOR 循环中的 DOM。

请看我的代码。

$("#btn").on("click", dowork);

function dowork() {
  document.getElementById("foo").innerHTML = "working";
  setTimeout(function() {
    var counter = 100; // i want assign counter = 2000000000
    for (var i = 0; i < counter; i++) {
      document.getElementById("print_here").innerHTML += i;
    }
    document.getElementById("foo").innerHTML = "done!";
  }, 50);
}
#btn {
  background: #1f1f1f;
  padding: 10px;
  font-weight: bolder;
  color: #fff;
  width: 50%;
  margin: auto;
  margin-top: 10px;
  text-align: center;
  cursor: pointer;
}

#print_here {
  overflow-wrap: break-word;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="btn">CLICK TO DO WORK</div>
<div id="foo"></div>
<div id="print_here"></div>

感谢您的回答和帮助解决这个问题。

您需要让调用堆栈完成,以便浏览器可以在页面上完成它的工作。如果您停滞在一个主线程中,页面更新将不会发生。

一种方法是使用 setImmediate 或 nextTick。这是非标准的,所以检查这个 polyfill:https://www.npmjs.com/package/browser-next-tick

基本上,您进行一次迭代,然后告诉浏览器尽快进行下一次迭代...这发生在新的调用堆栈上。

你的 DOM 是 "locked" 正在更新和重绘循环完成。您可以释放资源,让 DOM 更新每次将您的 DOM 更改包装在 setTimeout 中,类似于:

setTimeout(function(){
    document.getElementById("print_here").innerHTML += i;
},1);

要确保 setTimeout 使用 i 的正确值,请使用 let i 而不是 var i

$("#btn").on("click", dowork);

function dowork() {
  document.getElementById("foo").innerHTML = "working";

  var counter = 3000; // i want assign counter = 2000000000
  for (let i = 0; i < counter; i++) {
    setTimeout(function() {
      document.getElementById("print_here").innerHTML += i;
    }, 1);
  }
  document.getElementById("foo").innerHTML = "done!";
}
#btn {
  background: #1f1f1f;
  padding: 10px;
  font-weight: bolder;
  color: #fff;
  width: 50%;
  margin: auto;
  margin-top: 10px;
  text-align: center;
  cursor: pointer;
}

#print_here {
  overflow-wrap: break-word;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="btn">CLICK TO DO WORK</div>
<div id="foo"></div>
<div id="print_here"></div>

I want change the #foo into "done!" after the FOR statement is END

您可以检查您是否在 setTimeout 中处理的最后一项,类似于:

if (i == counter - 1){
    document.getElementById("foo").innerHTML = "done!";
}

$("#btn").on("click", dowork);

function dowork() {
  document.getElementById("foo").innerHTML = "working";

  var counter = 3000; // i want assign counter = 2000000000
  for (let i = 0; i < counter; i++) {
    setTimeout(function() {
      document.getElementById("print_here").innerHTML += i;
      if (i == counter - 1){
        document.getElementById("foo").innerHTML = "done!";
      }
    }, 1);
  }
}
#btn {
  background: #1f1f1f;
  padding: 10px;
  font-weight: bolder;
  color: #fff;
  width: 50%;
  margin: auto;
  margin-top: 10px;
  text-align: center;
  cursor: pointer;
}

#print_here {
  overflow-wrap: break-word;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="btn">CLICK TO DO WORK</div>
<div id="foo"></div>
<div id="print_here"></div>

这是适合您的工作代码:

$("#btn").on("click", dowork);

function dowork() {
  document.getElementById("foo").innerHTML = "working";
  setTimeout(function() {

    var i, j, row = 5;
    var html = "";
    for (i = 1; i <= row; i++) {
      for (j = 1; j <= i; j++) {
        html += "<span>" + j + "</span>";
      }
      html += "</br>";
    }
    console.log(html);
    document.getElementById("print_here").innerHTML = html;
  }, 50);
}
#btn {
  background: #1f1f1f;
  padding: 10px;
  font-weight: bolder;
  color: #fff;
  width: 50%;
  margin: auto;
  margin-top: 10px;
  text-align: center;
  cursor: pointer;
}

#print_here {
  overflow-wrap: break-word;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="btn">CLICK TO DO WORK</div>
<div id="foo"></div>
<div id="print_here"></div>

Rows是你要打印的行数。