Question

I am trying to call a member function from another member function - and failing. I figured this would be easy to find but after 10 minutes of searching I can't find what's wrong here.

In the following code (and yes I know pausecomp is a big no-no, I'm just trying to test against a possible race condition):

class LayoutWorker {
    /*
     Specific events handlers.
     e is the object sent by the client. See events.layout for object definitions.
     */
    handlers = {
        textadd: function (e) {
            for (var ind=0; ind<10; ind++)
            {
                console.log("entering textadd = " + e);
                // Do the work and call the client back if needed. You can pass to the client any object.
                e.text += " -- Hello back from the worker!";
                postClientMessage(e);

                this.pausecomp(4000);
            }
        },

        urgent: function (e) {
            for (var ind=0; ind<10; ind++)
            {
                console.log("entering urgent = " + e);
                // Do the work and call the client back if needed. You can pass to the client any object.
                e.text += " -- Hello back from the worker!";
                postClientMessage(e);

                this.pausecomp(1000);
            }
        }

    };

    handleEvent(e) {
        console.log("entering handleEvent = " + e);
        // Call the specific handler.
        this.handlers[e.id](e);
    }

    pausecomp(millis : number) : void
    {
        var date = new Date();
        var curDate = new Date();
        while(curDate - date < millis)
            curDate = new Date();
    }
}

When I run the above I get: Uncaught TypeError: Object # has no method 'pausecomp'

What do I have wrong?

thanks - dave

Was it helpful?

Solution 2

Inside your handlers object, this refers to handlers, not the class instance.

A reduced version:

class MyClass {
    handlers = {
        name: 'handlers',
        foo() {
            console.log(this.name);
        }
    }

    name = 'MyClass';

}

var x = new MyClass();
x.handlers['foo'](); // Prints 'handlers', not 'MyClass';

My recommendation would be to pass the class instance to the handler functions as an additional argument, or even better to just refactor this pattern entirely. As written it doesn't really make sense -- you're creating a new handlers object for every instance of the class, even though they belong on the prototype (because they don't hold instance data).

OTHER TIPS

In your example, this refers to the function of handler. You could also use a lambda expression (() =>) or an instance function (foo() {}).

If you're using a lambda, this should refer to MyClass. Here are some options for defining a class instance function: http://bit.ly/1ep5dMk

Because handlers is a seperate class with members for it's own, it cannot refer to LayoutWorker - unless you use a lambda.

You've got 3 options:

  • pass an instance of LayoutWorker somewhere
  • declare the pausecomp method as public and static and use LayoutWorker.pausecomp(arg) to call.
  • use a lambda (see examples of the TypeScript playground)

I created a little overview of the 3 mentioned options: http://bit.ly/1kOeWtS

Some recommendation:

Define a handler interface and/or seperate classes to get a clearer view of your class model. This helps understanding that this cannot refer to the LayoutWorker.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top