settimeout 并等待是否已设置超时

settimeout and wait if timeout already set

如何为 settimeout 函数创建队列。

我想创建带有 settimeout 的函数以在 2 秒后打印控制台,但是如果相同的 settimeout 已经在等待执行,新的超时函数应该在第一个完成后执行

<script>
function print_console(text,time)
{
   if(timeout is not already set)
   {
      timeout=setTimeout(function(){console.log(text);},time);
   }
   else
   {
     time=addition of time of already setted timeout + argument time
     timeout=setTimeout(function(){console.log(text);},time);
   }
}
print_console('i will print in 1000 minisec',1000);
print_console('i will print in 3000 minisec',2000);
print_console('i will print in 6500 minisec',3500);
.................
.............
</script>

我希望控制台输出屏幕上有此函数的输出--

我将在 1000 秒内打印 --- 07/08/2019 04:01:01

我将在 3000 秒内打印 --- 07/08/2019 04:01:03

我将在 6500 秒内打印 --- 07/08/2019 04:01:06

您可以将额外的呼叫保存到队列中,然后在计时器结束时处理它:

var print_console_stack = [], print_console_timeout = null;

function print_console(text,time)
{
   if(!print_console_timeout)
   {
      print_console_timeout = setTimeout(function(){
          console.log(text);
          print_console_timeout = null; //reset this timeout

          var next = print_console_stack.shift();
          if (next) {
              print_console(next.text, next.time);
          }
      }, time);
   }
   else
   {
     print_console_stack.push({text: text, time: time});
   }
}
print_console('i will print in 1000 millisec',1000);
print_console('i will print in 3000 millisec',2000);
print_console('i will print in 6500 millisec',3500);

您可以使用 promises:

function print_console(text,time){
  var p = new Promise(function(resolve, reject) {
    setTimeout(function() {
      console.log(text);
      resolve()
    }, time);
  });
  return p;
}

print_console('i will print in 1000 minisec',1000).then(function() {
  return print_console('i will print in 3000 minisec',2000);
}).then(function() {
  return print_console('i will print in 6500 minisec',3500);
});

您可以为此使用 async/await

(async () => { 
  async function print_console(text,time) {
    await new Promise((res, rej) => {
      setTimeout(() => (console.log(text), res()), time);
    });
  }

  await print_console('i will print in 1000 minisec',1000);
  await print_console('i will print in 3000 minisec',2000);
  await print_console('i will print in 6500 minisec',3500);
})();


编辑:OP 想在此范围之外调用它。然后我会使用另一种方法,使用 IFEE 将数组、标志 var 和函数调用者存储到函数范围中:

const print_console = (() => {
  const arr = [];
  let isProcessing = false;
  
  setInterval(() => {
    if(isProcessing) return;
    
    const next = arr.shift();
    if(next) {
      isProcessing = true;
      setTimeout(() => {
        console.log(next.text);
        isProcessing = false;
      }, next.time);
    }
  });
  
  return (text, time) => {
      arr.push({text, time});
  } 
})();


print_console('i will print in 1000 minisec',1000);
print_console('i will print in 3000 minisec',2000);
print_console('i will print in 6500 minisec',3500);

您可以创建一个函数队列,每个函数将执行一个 setTimeout。然后,当一个setTimeout被执行时,你可以得到队列的下一个函数an被执行。

下面是一个完整的工作示例:

var timeQueue = [];
function onClick() {
  print_console(`The button was clicked!`, 2000);
}

function printALot() {
   print_console(`Row 1!`, 2000);
   print_console(`Row 2!`, 5000);
   print_console(`Row 3!`, 300);
   print_console(`Row 4!`, 400);
   print_console(`Row 5!`, 2000);
   print_console(`Row 6!`, 3000);
   print_console(`Row 7!`, 400);
   print_console(`Row 8!`, 3000);
   print_console(`Row 9!`, 400);
}

function print_console(text, time) {

  let localTime = time;
  let functionToExecute = () => {
    setTimeout(() => {
      console.log(text);
      timeQueue.pop();
      execute_next_print_console();
    }, localTime);
  }
  timeQueue.push(functionToExecute);
  if(timeQueue.length === 1) {
   execute_next_print_console();
  }
 
}

function execute_next_print_console() {
  if(timeQueue.length > 0) {
    let functionToExecute = timeQueue[0];
    functionToExecute();
  }
}
<button onclick="onClick()">click me!!!!</button>
<button onclick="printALot()">Print a lot!</button>