循环内的 setTimeout 行为

setTimeout behaviour inside a loop

我一直在寻找如何在循环中使用 setTimeout 函数,但关于这方面的文档似乎有限,我想在 for 循环中创建一个 setTimeout,它本身嵌入在 while 循环中。 浏览器似乎只执行一次 setTimeout 以及这个 code show it.

 var value = 0 
 var arr = [65, 59, 80, 81, 56, 70, 72, 89, 23, 11, 4, 92, 87, 84, 50, 57, 59, 44, 49, 39, 35, 32, 0]

 while(value < 10){
   const span = document.createElement('span')
   span.innerText = value
   setTimeout(() => {
     document.getElementById('spans').appendChild(span)
   },1000)
   value++
 }

任何人都可以解释这种行为,以及如何继续让 setTimeout 在循环内的每个地方执行。

setTimeout是否以异步方式执行。

setTimeout 不像睡眠。没有停顿。它会在您指定的时间向 运行 注册一些代码。所以你在 1 秒内完成了 10 件事 运行。

因此,要使您的代码正常运行,您必须将 1 秒乘以循环索引。所以它们是偏移

 var value = 0 
 var arr = [65, 59, 80, 81, 56, 70, 72, 89, 23, 11, 4, 92, 87, 84, 50, 57, 59, 44, 49, 39, 35, 32, 0]

 while(value < 10){
   const span = document.createElement('span')
   span.innerText = value
   setTimeout(() => {
     document.getElementById('spans').appendChild(span)
   },1000 * value)
   value++
 }
<div id="spans"></div>

现在大多数开发人员不会生成一堆超时。他们要么使用队列,要么使用 setInterval。

var value = 0

function nextValue() {
  const span = document.createElement('span')
  span.innerText = value
  document.getElementById('spans').appendChild(span)

  value++;
  if (value < 10) {
    window.setTimeout(nextValue, 1000);
  }
}


nextValue();
<div id="spans"></div>

或区间

var value = 0;
var timer;

function update() {
  const span = document.createElement('span')
  span.innerText = value
  document.getElementById('spans').appendChild(span)
  value++;
  if (value === 10) {
    window.clearTimeout(timer);
  }
}


timer = window.setInterval(update, 1000);
update();
<div id="spans"></div>

//<![CDATA[
/* js/external.js */
let doc, htm, bod, nav, M, I, mobile, S, Q;
addEventListener('load', ()=>{
doc = document; htm = doc.documentElement; bod = doc.body; nav = navigator; M = tag=>doc.createElement(tag); I = id=>doc.getElementById(id);
mobile = nav.userAgent.match(/Mobi/i) ? true : false;
S = (selector, within)=>{
  var w = within || doc;
  return w.querySelector(selector);
}
Q = (selector, within)=>{
  var w = within || doc;
  return w.querySelectorAll(selector);
}
// magic under here - you can put all but end load on a separate page if desired
const arr = [65, 59, 80, 81, 56, 70, 72, 89, 23, 11, 4, 92, 87, 84, 50, 57, 59, 44, 49, 39, 35, 32, 0];
const arrCount = arr.length, spans = I('spans');
let i = 0;
let interval = setInterval(()=>{
  let span = M('span');
  span.textContent = arr[i++]; spans.appendChild(span);
  if(i === arrCount){
    clearInterval(interval); interval = undefined;
  }
}, 1000);
}); // end load
//]]>
/* css/external.css */
*{
  box-sizing:border-box; color:#000; padding:0; margin:0;
}
html,body,.main{
  width:100%; height:100%;
}
.main{
  background:#333; padding:10px;
}
#spans>span{
  color:#fff; font:bold 12px Tahoma, Geneva, sans-serif;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
  <head>
    <meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1, user-scalable=no' />
    <title>Title Here</title>
    <link type='text/css' rel='stylesheet' href='css/external.css' />
    <script src='js/external.js'></script>
  </head>
<body>
  <div class='main'>
    <div id='spans'></div>
  </div>
</body>
</html>

setTimeout 您需要一个“异步”循环,例如

var COUNTER = 1;
var LOOP = (DONE) => {
  setTimeout (() => {
     COUNTER++;
     console.log ("ITERATION");

     if (COUNTER === 10) {
         DONE ();
         return;
     }

     LOOP (DONE);
  }, 100);
} 

LOOP (() => {
  console.log ("DONE");
});