0
class MyExampleClass {
    constructor(port, service) {
        this.port = port;
        this.service = service;
        this.app = require('express')();
        this.http = require('http').createServer(this.app);
    }

    onListening() {
        // Current result: 'listening on port NaN for undefined'
        // Desired result: 'listening on port 3000 for test' (I want to CHANGE this behavior)
        console.log('listening on port %d for %s', this.port, this.service);

        // Current result: 'class: Server'
        // Desired result: 'class: Server' (I want to KEEP this behavior)
        console.log('class: ' + this.constructor.name);
    }

    start() {
        this.http.listen(this.port, this.onListening);
    }
}

const example = new MyExampleClass(3000, 'test');
example.start();

As stated in the comments of the onListening method, I want to access both the context of the instance of MyExampleClass and the callback instance of Server created by createServer.

3
  • A common technique is to put const self=this somewhere before the context switch and using self instead of this when referencing the other context Commented Aug 27, 2019 at 6:27
  • @DovRine how would I do that cleanly if I have my callback as a separate method? Would I have to pass self in as another parameter to onListening or is there a better way so as not to alter the method signature? Commented Aug 27, 2019 at 6:29
  • I posted an answer that might help Commented Aug 27, 2019 at 6:38

4 Answers 4

4

Bind this.onListening in the constructor to preserve the this context inside onListening.

You can't have this point to 2 different contexts so you will have to access the Server instance through this.http.

class MyExampleClass {
    constructor(port, service) {
        this.port = port;
        this.service = service;
        this.app = require('express')();
        this.http = require('http').createServer(this.app);

        this.onListening = this.onListening.bind(this);
    }

    onListening() {
        console.log('listening on port %d for %s', this.port, this.service);
        console.log('class: ' + this.http.constructor.name);
    }

    start() {
        this.http.listen(this.port, this.onListening);
    }
}

const example = new MyExampleClass(3000, 'test');
example.start();
Sign up to request clarification or add additional context in comments.

7 Comments

The first call to log in onListening has the desired behavior, but not the second call to log. The second call now logs class: MyExampleClass.
@Hank then change this.constructor.name to this.http.constructor.name
what do you expect to be printed out in the second log? this solution is correct, constructor.name is the name of the class
@AdamKosmala the question lists the desired and actual outputs that are printed.
@Hank You can't have this point to 2 different contexts, use this.http.constructor.name to access the Server instance
|
2

Use arrow functions

class ExampleServer {
  constructor (port, service) {
    this.port = port
    this.service = service
    this.app = require('express')()
    this.http = require('http').createServer(this.app)
  }

  onListening = () => {
    console.log('listening on port %d for %s', this.port, this.service)
  }

  start = () => {
    this.http.listen(this.port, this.onListening)
  }
}

const server = new ExampleServer(3000, 'test')
server.start()

1 Comment

SyntaxError: Unexpected token =
2

Just use bind(this) on your callback reference like this this.http.listen(this.port, this.onListening.bind(this));

following the code will work


class ExampleServer {
    constructor(port, service) {
        this.port = port;
        this.service = service;
        this.app = require('express')();
        this.http = require('http').createServer(this.app);
    }

    onListening() {
        // I want to access the context for the instance of `ExampleServer`, but `this` is the context for the instance of `Server` created by `createServer`.
        console.log('listening on port %d for %s', this.port, this.service);

        // I want to also still be able to access the context for the instance of `Server` created by `createServer`, which is what the below is already doing.
        console.log(this.http.constructor);
    }

    start() {
        this.http.listen(this.port, this.onListening.bind(this));
    }
}

const server = new ExampleServer(3000, 'test');
server.start();

1 Comment

This doesn't give me the desired behavior that I want. See my edit to the question.
-4

How about something like this?

onListening(server=null) {
   const self = this;
        // I want to access the context for the instance of `ExampleServer`, but `this` is the context for the instance of `Server` created by `createServer`.
       if(server){
            console.log('listening on port %d for %s', server.port, server.service);
       }
        // I want to also still be able to access the context for the instance of `Server` created by `createServer`, which is what the below is already doing.
        console.log(self);
    }

5 Comments

This is bad design, for instance you can look @krishna's answer to solve it in a more elegant way.
@AlejandroGarciaAnglada: This is not bad design. See: Javascript var self = this; vs. .bind (gist.github.com/jashmenn/b306add36d3e6f0f6483)
It's bad design in a sense that it just doesn't work. If you set self = this in the same context where you use self, it's exactly equivalent to just using this directly. The self = this must be done earlier, where the value of this is guaranteed to be what you want.
@JJJ: My mistake. You are correct. Thanks for pointing it out.
Correct, I was meaning what @JJJ said.

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.