0

I'm trying to return a value from my setInterval function. My code looks like that:

export const timeCounter = () => {
  const date = "2018-08-12T18:45:00.000Z"; //this is just mocked data
  const matchDate = new Date(date);

  let dateToShow;

  const showTime = () => {
    const currentDate = new Date();
    const distance = matchDate - currentDate;

    return dateToShow = distance < 0 ? "FINISHED" : null;
  };


  const timer = setInterval(showTime, 1000);
  console.log(timer) // here I'd like to see refreshing value (FINISHER or nothing)
};

What I'm trying to do is to run my interval every second with showTime function. What I need to return is just "FINISHED" or nothing. But console.log(timer) won't give refreshed status. Thanks for helping.

OliverRadini
  • 6,238
  • 1
  • 21
  • 46
Murakami
  • 3,474
  • 7
  • 35
  • 89

3 Answers3

1

The problem you're having is that timer is set to the result of the setInterval function, not the return value of the function within setInterval. setInterval just returns a reference that you can use to cancel it.

If you pass a callback function into the timer, it'll be able to run that function once it reaches the condition you set:

const timeCounter = () => {
  const date = "2018-08-12T18:45:00.000Z"; //this is just mocked data
  const matchDate = new Date(date);

  let dateToShow;

  const showTime = (callback) => {
    const currentDate = new Date();
    const distance = matchDate - currentDate;

    return dateToShow = distance < 0 ? callback("FINISHED") : null;
  };


  const logWhenDone = logData => console.log(logData)

  const timer = setInterval(() => {showTime(logWhenDone)}, 1000);
  
  // this is just the return value of the setInterval function, which is just a reference to that interval
  console.log(timer) 
};

timeCounter()

To return something from the function you need to handle the fact that the function is asynchronous, that is, it will evaluate to the return statement before it has the actual value it needs to return.

There are a few different ways to handle asynchronous code. One way would be to pass the callback into timeCounter as has been done with showTime. Another way is to return a Promise, that will resolve once the timer hits its end condition.

const timeCounter = () => {
  const timerPromise = new Promise((resolve, reject) => {
    const date = "2018-08-12T18:45:00.000Z"; //this is just mocked data
    const matchDate = new Date(date);

    const showTime = () => {
      const currentDate = new Date();
      const distance = matchDate - currentDate;

      if (distance < 0) {
        return resolve("FINISHED");
      }
    };

    setInterval(showTime, 1000);
  });
  
  return timerPromise;
};

timeCounter().then(response => console.log(`The response is ${response}`));

EDIT Based on what you've said regarding wanting to respond to every tick of the setInterval, you may want to consider using events instead:

const date = "2018-08-12T18:45:00.000Z";
const matchDate = new Date(date);

setInterval(() => {
  const currentDate = new Date();
  const distance = matchDate - currentDate;
  
  var tick = new CustomEvent('tick', {
    detail: distance < 0 ? 'FINISHED' : '',
  });
  
  document.dispatchEvent(tick);
}, 1000);

document.addEventListener('tick', event => console.dir(event.detail));
OliverRadini
  • 6,238
  • 1
  • 21
  • 46
1

setInterval does not return the string 'FINISHED' or null you expect but It returns an interval ID which uniquely identifies the interval, so you can remove it later by calling clearInterval(). This method is offered on the Window and Worker interfaces.

Peter
  • 10,492
  • 21
  • 82
  • 132
0

Return Value: A Number, representing the ID value of the timer that is set. Use this value with the clearInterval() method to cancel the timer

you can log refreshing value inside showTime function:

const showTime = () => {
    const currentDate = new Date();
    const distance = matchDate - currentDate;

    dateToShow = distance < 0 ? 'FINISHED' : null;

    console.log(dateToShow);
};

or use component`s state if you want to refresh DOM

Igor Alemasow
  • 4,484
  • 2
  • 27
  • 24