-1

This code is part of a game where the user has a certain amount of time to input an answer.

I want to be able to clear the interval from outside of the object if the user decides to submit an answer before the allotted time has elapsed.

I have tried returning the interval with an ID so that I can call it later and whilst this does allow me to clear it from outside the outside the object, it means that the code inside the interval function is never run.

const clock = {
    timer: 30,
    countdown() {
        let interval = setInterval(function () {
            selectors.timerDisplay.textContent = clock.timer
            clock.timer--
            if (clock.timer < 0) {
                clearInterval(interval)
                selectors.wordSubmit.click();
            }
        }, 1000)
    },
}

I appreciate I may have simply set myself up badly to clear this interval, therefore any suggestions on how I could improve it would be appreciated.

Thanks in advance.

  • so store it was part of clock `clock.interval = setInterval...` – epascarello Feb 07 '18 at 23:05
  • If you change `function ()` to `() =>` you can use `this.timer` instead of `clock.timer`, but I don't see any problems right now.. did you get an error or something? – Patrick Roberts Feb 07 '18 at 23:05
  • 1
    Is there a reason you don't just `return interval;` at the end of `countdown`? – Heretic Monkey Feb 07 '18 at 23:07
  • _" it means that the code inside the interval function is never run"_ <- which is precisely why one would call `clearInterval` – Phil Feb 07 '18 at 23:08
  • @Phil that is correct, however, I do want the code to run, up until the point the user is ready to move on. It is entirely possible it runs all the way to 0 but I'd like to give the user the option of moving on earlier. – msweeneydev Feb 07 '18 at 23:14
  • I'm not understanding the problem. If you return the `interval` as suggested by @MikeMcCaughan, you can call `clearInterval` at any point in time afterwards and the interval will run every second until you do so – Phil Feb 07 '18 at 23:16
  • @Phil I tried returning `interval` at the end of the function but if I use `window.clearInterval(interval)` it is undefined. I was able to make this work by returning the first line of the function but then the code never runs. – msweeneydev Feb 07 '18 at 23:28
  • You'd have to have something like `let interval = clock.countdown()`. Then you'd be able to clear it via `interval` later on. How about you start adding your code attempts to your question so we can stop this guessing game? – Phil Feb 07 '18 at 23:31

3 Answers3

2
  • You can use Arrow functions to leverage the context of this from your object clock
  • Add a method i.e clear.
  • Use this context to reference your inner attributes.

const clock = {

    timer: 3,
    interval: 0,
    
    reset() {
      this.timer = 3;
      this.interval = 0;
    },
    
    clear() {      
      clearInterval(this.interval);
      this.reset();
    },
    
    countdown() {
        this.interval = setInterval(() => {
            //selectors.timerDisplay.textContent = clock.timer
            this.timer--;
            console.log(this.timer)
            if (this.timer < 0) {                
                clearInterval(this.interval)
                //selectors.wordSubmit.click();
            }
        }, 1000);
    },
}

clock.countdown();
setTimeout(function() {
  clock.clear();
}, 1500)

See? the interval function ends after 1.5secs

Ele
  • 33,468
  • 7
  • 37
  • 75
0

You can expose a method to clear the interval

const selectors = document.querySelector('div');
const clearTimer = document.querySelector('button');
const clock = {
    timer: 5,
    // Initiate the interval
    int: null,
    // This exposes a way to clear the interval outside of the object
    clearTimer() {
      clearInterval(this.int);
    },
    countdown() {
        // This is where you define this.int
        this.int = setInterval(() => {
            //selectors.timerDisplay.textContent = clock.timer
            selectors.innerText = clock.timer.toString();
            clock.timer--
            console.log(clock.timer);
            if (clock.timer < 0) {
                this.clearTimer();
                //selectors.wordSubmit.click();
            }
        }, 1000)
    },
}

clock.countdown();
clearTimer.addEventListener('click', () => {
  clock.clearTimer();
})
<div>clock.timer</div> 
<button>clear timer</button>
msorce
  • 31
  • 3
0

As has been suggested in the comments, simply return the interval so it can be stopped later. For example

countdown() {
    let interval = setInterval(function () {
        selectors.timerDisplay.textContent = clock.timer
        clock.timer--
        if (clock.timer < 0) {
            clearInterval(interval)
            selectors.wordSubmit.click();
        }
    }, 1000)
    return interval // added this line
},

Then, consumers can cancel the interval when they want

const interval = clock.countdown()

// and later...

clearInterval(interval)
Phil
  • 157,677
  • 23
  • 242
  • 245
  • Thanks, @Phil, apologies it took me a while to grasp this. I didn't understand you needed to assign a variable to it and was just trying `clearInterval(clock.countdown())` with no luck - this makes much more sense now and unsurprisingly works. – msweeneydev Feb 07 '18 at 23:58