输入新起点时清除 javascript 计时器

Clearing a javascript timer when new starting point is input

是的,我是新来的,别担心让我听起来很蠢。 :) 这是一个用 Google 脚本编写的网络应用程序,它从 Google 表格中获取信息。

我采用了此处评论中的代码:Javascript timer to use multiple times in a page。当前代码如下。在这整个过程中,我 运行 有几个不同的计时器,它们每秒都减少 1 秒 - 太棒了。我的问题是因为第一个代码获取的 google sheet 的值每隔几分钟就会改变一次。我希望它从最近的数据开始倒计时,并使 "old" 计数器停止。通过阅读几个相关的线程,我认为我在某处需要另一个 clearInterval,但我不知道把它放在哪里。

Google Apps 获取 Google sheet 值并将它们放入变量中的脚本。 "getdata" 值是未来的日期,然后 "data" 是距离该日期还有多少秒:

    function getfivecoins(){
      var livesheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Live");
      var getdata = livesheet.getRange("D42").getValue().getTime();
      var now = new Date().getTime();
      var data = (getdata-now)/1000; // how many seconds in the future this date is
      return data;
    }


function gettencoins(){
  var livesheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Live");
  var getdata = livesheet.getRange("D43").getValue().getTime();
  var now = new Date().getTime();
  var data = (getdata-now)/1000;  // how many seconds in the future this date is
  return data;
}

然后在 html 页:

<span id="timer1"></span>
    <br>
<span id="timer2"></span>
    <br>

在脚本标签内向下:

// 每 10 秒,从 google sheets 获取新值。如果值相同,倒计时应该继续正常进行(有几毫秒的差异,无论如何),但如果值已更改,则尝试让倒计时重新开始。如果更简单,清除所有倒计时然后重新开始应该会有相同的结果。

  document.addEventListener('DOMContentLoaded', function(){
        setInterval(function(){
        google.script.run.withSuccessHandler(generatefivecoins).getfivecoins();
        google.script.run.withSuccessHandler(generatetencoins).gettencoins();
}, 10000);
        });


const clearStack = []; //Added
   function generatefivecoins(result) {
   clearStack.forEach(clearInterval); //Added
   var timer = document.getElementById('timer1');
   var t = new timerObject();
   clearStack.push(t.startTimer(result, timer)); //Modified
   }

    function generatetencoins(result){
    clearStack.forEach(clearInterval); //Added
    var timer =  document.getElementById("timer2");
    var t = new timerObject();
    clearStack.push(t.startTimer(result, timer)); //Modified
    } 





     var timerObject = function(){
    return this;
};

timerObject.prototype.startTimer = function(duration, display) {
  var me = this, 
      timer = duration,
      STYLETEST, hours, minutes, seconds, ENDSTYLETEST; 
var intervalLoop = setInterval(() => { // modified this line

    //fancy colours and formatting stuff goes here

  display.innerHTML = STYLETEST + " " + hours + ":" + minutes + ":" + seconds + ENDSTYLETEST;

    if (--timer < 0) {
      clearInterval(intervalLoop);
    }    
  }, 1000);
    return intervalLoop; //Added  
};

流量:

  • 我们使用带有可变参数的单个函数,而不是多个函数。
  • coinBucket持有可生成的不同硬币
  • 从服务器端调用 generateCoins 后,我们使用 Map to store timerObject instance of class 。在下一次调用期间,我们使用相同的 timerObject 而不是创建一个新的。

code.gs

function doGet(e) {
  return HtmlService.createHtmlOutputFromFile('index');
}

const getCoins = coin => {
  const map = { 5: 'D42', 10: 'D43', 20: 'D48', 60: 'D49', 90: 'D50' };//fivecoin range = D42 and so on
  var livesheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Live');
  var getdata = livesheet
    .getRange(map[coin])
    .getValue()
    .getTime();
  var now = new Date().getTime();
  var data = getdata - now; // how many milliseconds in the future this date is
  return data;
};

客户端:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title></title>
  </head>
  <body>
    <h1>Coins!!</h1>
    <span id="timer1"></span>
    <span id="timer2"></span>
    <span id="timer3"></span>
    <span id="timer4"></span>
    <span id="timer5"></span>
  </body>
  <script>
    const coinBucket = [5, 10, 20, 60, 90];//number of coin buckets 
    const GSR = (func, ...args) =>// google.script.run to promise
      new Promise((resolve, reject) =>
        google.script.run
          .withSuccessHandler(resolve)
          .withFailureHandler(reject)
          [func](...args)
      );

    const clearStack = new Map();//map to store timerObjects
    function generateCoins(result, i) {
      const timer = clearStack.get(i) || new timerObject(i);
      clearStack.set(i, timer);
      timer.stopTimer();
      timer.startTimer(result);
    }
    class timerObject {
      constructor(id) {
        this.elementId = 'timer' + (id + 1);
        this.timerIds = [];
      }
      startTimer(duration) {
        const display = document.getElementById(this.elementId);
        this.timerIds.push(
          setInterval(() => {
            const hours = parseInt(duration / 1000 / 60 / 60, 10),
              minutes = parseInt((duration / 1000 / 60) % 60, 10),
              seconds = parseInt((duration / 1000) % 60, 10);
            display.innerHTML = [hours, minutes, seconds]
              .map((e) => ('0' + e).slice(-2))
              .join(':');
            duration = duration - 1000;
            if (duration < 0) this.stopTimer();
          }, 1000)
        );
      }
      stopTimer() {
        this.timerIds.forEach(clearInterval);
        this.timerIds = [];
      }
    }

    document.addEventListener('DOMContentLoaded', function () {
      setInterval(function () {
        Promise.all(
          coinBucket.map((bucket) => GSR('getCoins', bucket))
        ).then((values) => values.forEach(generateCoins));
      }, 10000);
    });
  </script>
</html>