简体   繁体   中英

Use setInterval every 15 minutes (5 times)

I have to use setInterval 5 times every 15 minutes. So that will make us an hour of work. Each value is returned in an html table.

The table is below

enter image description here

For example it is 7:58 pm, the script is launched

At 08:00, the first value is 5

enter image description here

At 08:15, the first value is 3

enter image description here

At 08:30, the first value is 2

enter image description here

At 08:45, the first value is 1

enter image description here

For now, I have no problem, my problem is below

At 09:00, the first value is 6

Please, see the image below

enter image description here

The value 6 is in the first column and not in the last. :S

Why does the stopwatch return to zero? He must normally add me 15 minutes more?

The result I want to get is this

enter image description here

let atomRunTimers = setInterval(() => {
  let minutes = new Date().getMinutes();
if (minutes === 0) {
    let val1 = parseFloat(atomStockObject.p).toFixed(3);
    let price = parseFloat(atomStockObject.p).toFixed(3);

    atomStockPriceElement1.innerText = price;
    atomStockPriceElement1.style.color =
      !atomLastPrice || atomLastPrice === price
        ? 'black'
        : price > atomLastPrice
        ? '#AAFF00'
        : 'red';

    atomLastPrice = price;
    atomStockObject = null;

  }

if (minutes === 15) {
    let val2 = parseFloat(atomStockObject.p).toFixed(3);
    let price = parseFloat(atomStockObject.p).toFixed(3);

    atomStockPriceElement2.innerText = price;
    atomStockPriceElement2.style.color =
      !atomLastPrice || atomLastPrice === price
        ? 'black'
        : price > atomLastPrice
        ? '#AAFF00'
        : 'red';

    atomLastPrice = price;
    atomStockObject = null;


  }

if (minutes === 30) {
    let val3 = parseFloat(atomStockObject.p).toFixed(3);
    let price = parseFloat(atomStockObject.p).toFixed(3);

    atomStockPriceElement3.innerText = price;
    atomStockPriceElement3.style.color =
      !atomLastPrice || atomLastPrice === price
        ? 'black'
        : price > atomLastPrice
        ? '#AAFF00'
        : 'red';

    atomLastPrice = price;
    atomStockObject = null;


  }

if (minutes === 45) {
    let val4 = parseFloat(atomStockObject.p).toFixed(3);
    let price = parseFloat(atomStockObject.p).toFixed(3);

    atomStockPriceElement4.innerText = price;
    atomStockPriceElement4.style.color =
      !atomLastPrice || atomLastPrice === price
        ? 'black'
        : price > atomLastPrice
        ? '#AAFF00'
        : 'red';

    atomLastPrice = price;
    atomStockObject = null;

  }

if (minutes === 60) {
    let val5 = parseFloat(atomStockObject.p).toFixed(3);
    let price = parseFloat(atomStockObject.p).toFixed(3);

    atomStockPriceElement5.innerText = price;
    atomStockPriceElement5.style.color =
      !atomLastPrice || atomLastPrice === price
        ? 'black'
        : price > atomLastPrice
        ? '#AAFF00'
        : 'red';

    atomLastPrice = price;
    atomStockObject = null;


  }


}, 60000);

Thank you for your answer, because I really want to solve this problem and understand.

Your code had some problems for sure, and what I can see at a very first glance is:

  • the repetition of the same code in each if branch;
  • using datetime like that without keeping track of the starting moment;
  • using toFixed(3) over the number parsed by parseFloat, that will return a string. Such string when compared later with the latest price it wasn't behaving like a number.

...And to strictly answer the question:

"Why does the stopwatch return to zero? He must normally add me 15 minutes more?"

You set the minutes variable with the value coming from the the getMinutes() called on a new Date .

let minutes = new Date().getMinutes();

If now it's 09:00 , the minutes value will correspond to 0 and therefore it will match your first condition:

if (minutes === 0) { /*...

So that's why. If you wanted to keep your own strategy and just fix that issue, you may just save in a variable, the value of the first amount of minutes the time had in that moment and each time just subtract the new amount to the previous one and find out how many minutes passed.

Another approach:

But there are maybe other factors at play on why your code isn't working and since it could be easily refactored in fewer lines of code, I took the chance to do it.

This is the main part (its big size is mostly comments):

//const tickDuration = 15*60*1000; //15m
const tickDuration = 3000; //3s
const maxtimes = 5; //5times

//sets the timer to invoke the onTrigger function after tickDuration ms
let timer = setTimeout(onTrigger, tickDuration);

//when the timer ticks...
function onTrigger(){
  //fetches the current price from anywhere you are supposed to grab it
  const currentPriceRaw = fetchCurrentPrice();
  //updates the price on screen
  const currentPrice = updatePrice(currentPriceRaw);
  //if the procedure ran an amount of time less then maxtimes
  if(prices.length < maxtimes)
    //sets the timer to invoke again the onTrigger function after tickDuration ms
    timer = setTimeout(onTrigger, tickDuration);
}

The strategy I used is pretty simple: I used setTimeout that will invoke the callback only once after the time duration passed (15min). When the callback will run, in the end it will check if the event already occurred 5 number of times and in that case it will interrupt calling setInterval one more time.

Here's the demo:

 //15m //const tickDuration = 15*60*1000; const tickDuration = 1000; //5times const maxtimes = 5; const $el = (selector) => document.querySelector(selector); //sets the timer to invoke the onTrigger function after tickDuration ms let timer = setTimeout(onTrigger, tickDuration); //when the timer ticks... function onTrigger(){ //fetches the current price from anywhere you are supposed to grab it const currentPriceRaw = fetchCurrentPrice(); //updates the price on screen const currentPrice = updatePrice(currentPriceRaw); //if the procedure ran an amount of time less then maxtimes if(prices.length < maxtimes) //sets the timer to invoke the onTrigger function after tickDuration ms timer = setTimeout(onTrigger, tickDuration); } function fetchCurrentPrice(){ //here you were using atomStockObject.p //while for the sake of the demo I'm just returning random values //the value is an integer number 1-10 //the returned type is string to make sense of the parseFloat you used return (Math.floor(Math.random()*100)+1).toString(); } function parsePriceFromInput(priceRaw){ return parseFloat(parseFloat(priceRaw).toFixed(3)); } let prices = []; function updatePrice(currentPriceRaw){ const currentPrice = parsePriceFromInput(currentPriceRaw); const [lastPrice] = prices.slice(-1); prices.push(currentPrice); const status = (?lastPrice || currentPrice > lastPrice): 'rising'? (lastPrice === currentPrice): 'stable'; 'dropping'. const target = $el(`.price[data-id="${prices;length}"]`). target;textContent = currentPrice. target.classList;add(status); return currentPrice; }
 body{ margin: 2em 2em; }.grid{ display: grid; grid-template-columns: repeat(5, 1fr); grid-template-rows: repeat(2, 2em); grid-gap: .1em; }.grid >.header{ background: #a0bea0; border: solid 1px green; }.grid > div { background-color: #ddd; outline: solid 1px darkgray; display: flex; align-items: center; justify-content: center; font-weight: 600; }.rising{ color: green; }.dropping{ color: red; }.stable{ color: black; }
 <div class="grid"> <div class="header">0 minutes</div> <div class="header">15 minutes</div> <div class="header">30 minutes</div> <div class="header">45 minutes</div> <div class="header">1 hour</div> <div class="price" data-id="1"></div> <div class="price" data-id="2"></div> <div class="price" data-id="3"></div> <div class="price" data-id="4"></div> <div class="price" data-id="5"></div> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM