Hank
Hank

Reputation: 125

How to access both contexts of "this" in a callback function?

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.

Upvotes: 0

Views: 483

Answers (4)

Aviso
Aviso

Reputation: 695

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();

Upvotes: 2

Asaf Aviv
Asaf Aviv

Reputation: 11770

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();

Upvotes: 4

Medet Tleukabiluly
Medet Tleukabiluly

Reputation: 11930

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()

Upvotes: 2

Dov Rine
Dov Rine

Reputation: 840

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);
    }

Upvotes: -4

Related Questions