【问题标题】:settimeout and wait if timeout already setsettimeout 并等待是否已设置超时
【发布时间】:2019-08-07 10:34:57
【问题描述】:

如何为 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

【问题讨论】:

    标签: javascript queue settimeout


    【解决方案1】:

    您可以为此使用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);

    【讨论】:

    • 但是先生,我想从外面调用 print_console()
    • @HarendraChauhan 哦,我不知道。我刚刚更新了我的帖子,提出了另一种方法。 ;)
    • 非常感谢先生您的快速回复并解决了我的问题。
    • @HarendraChauhan 太棒了!如果你觉得这有帮助,你可以投票赞成这个答案:)
    • 我在这里呆了 5 个月,你的程序很棒并且工作正常,但是当我在 Internet Explorer 中执行它时,它不工作。你能重新检查你的程序并在 IE11 中测试它吗?
    【解决方案2】:

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

    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);
    

    【讨论】:

      【解决方案3】:

      你可以使用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);
      });
      

      【讨论】:

        【解决方案4】:

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

        遵循一个完整的工作示例:

        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>

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-06-29
          • 1970-01-01
          • 1970-01-01
          • 2019-10-19
          • 1970-01-01
          • 1970-01-01
          • 2021-12-04
          相关资源
          最近更新 更多