0

This is a Vue class. The method signOut() should fire when the timer ticks. The timer works, except the call signOut().

The problem is with accessing the class method. I'm confused with this, self and access modifiers. I tried with this.signOut() but it does not work.

How can I call the method signOut?

"use strict";

(async (globals, config, loader, application) => {

    const storageLocal = await loader.services.storage.local.getAsync();

    class HeaderComponent {
        #foo = a;

        constructor(tag) {
            this.tag = tag;

            this.timer();
        }

        signOut() {
            storageLocal.delete('account');
            window.location = '/signin.html';
        }

        timer() {
            //document.getElementById("timer"), 
            var counter = -1;
            var timeout;
            var startTimer = function timer() {
                counter++;
                console.log(counter);

                signOut(); //<- error can't call class method
                timeout = setTimeout(timer, 10000);
            };

            function resetTimer() {
                // here you reset the timer...
                clearTimeout(timeout);
                counter = -1;
                startTimer();
                //... and also you could start again some other action
            }

            document.addEventListener("mousemove", resetTimer);
            document.addEventListener("keypress", resetTimer);
            startTimer();
        }

        data() {
            return { account: storageLocal.account };
        }
    }

    const component = new HeaderComponent('component-header')
    loader.components.set(component.tag, component);

})(window, window.config, window.loader, window.application);

Please note:

        signOut() {
            storageLocal.delete('account');
            window.location = '/signin.html';
        }

        timer() {
            //document.getElementById("timer"), 
            var counter = -1;
            var timeout;
            var startTimer = function timer() {

as you can see 'signOut()' is 2 levels below active functions. The logic says it would work like this.parent.signOut() but it DOES NOT !

EDIT3: this.signOut(); will produce

Uncaught TypeError: Cannot read property 'signOut' of undefined
    at timer (header.js:30)
    at HTMLDocument.resetTimer
1
  • 1
    Javascript doesn't automatically infer this as a prefix like C#, you want to use this.signOut() instead of just signOut(). Commented Nov 15, 2019 at 13:25

3 Answers 3

1

The function creates a new context. You need to switch to arrow function and use this.signOut(). Simplified example:

  timer() {
    var counter = -1;
    var timeout;
    var startTimer = () => {
      counter++;
      console.log(counter);

      this.signOut();
      timeout = setTimeout(startTimer, 1000);
    };

    setTimeout(startTimer, 1000);
  }

Moreover, you have two signOut() methods defined in one class.

Sign up to request clarification or add additional context in comments.

4 Comments

youre right . iremoved second method. still this.signOut(); doesnt work for me ((
Even after replacing function with arrow function as I shown above?
Actualy it works , sorry. But the timer fires immediatelly, not after xx seconds. how can i set it to run AFTER xx seconds not imediatelly
You can call startTimeout in a setTimeout(). See live demo: repl.it/repls/SuperficialPrettyBookmarks. If it works, I'll update the answer
0

You need this and call it like this.signOut()

1 Comment

doesnt help at all (
0

The startTimer-function does not run in the context of the HeaderComponent's instance. this in startTimer will point to window when it's executed as a handler in setTimeout.

In order to access the the instance of HeaderComponent, either use an arrow function (as pointed out in an earlier answer. See also Arrow function expressions) which will point this to the outer context (which is HeaderComponent's instance) or define an identifier in timer which points to the instance (eg. const self = this;) and use self instead of this in startTimer.

To apply this to your example (for the sake of consistency, I used var instead of const):

        timer() {
            var counter = -1;
            var timeout;
            var self = this;
            var startTimer = function() { // Don't use a named function here, it only leads to more confusion
                counter++;
                console.log(counter);

                self.signOut(); // Use `this` of the outer context
                timeout = setTimeout(startTimer, 10000);  // Use the declared identifier
            };

            // Rest of the method
        }

this is Javascript may be a bit confusing to those who come from different programming languages. If you want to get into more detail, I recommend reading into the MDN reference for this and into Closures

4 Comments

but where do i put 'const self = this;' inside constructor or outside? I've tried everything without luck
In the outer timer-function and then call self.signOut() in the inner timer-function.
hmm, when i put const self = this; just aboce timer() function then again i get error...
I've added the applied example to the answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.