Jeppe Christensen
Jeppe Christensen

Reputation: 1890

Extend subclass with callback function to superclass

I have two classes:

  1. Socket baseclass - Which handles basic operations for a socket connection
  2. Socket subclass - Which should apply specific operations i.e. when a message is received

In my application, I have multiple socket connections that I may open - Hence why I don't want to repeat all the logic for opening and closing my socket connection.

Similarly, when I receive a message on one of the connections I may handle the messages differently, depending on what connection I have opened.

Therefore, I came up with the following solution:

class SocketBase {
    constructor(messageHandler, errorHandler) {
        this.messageHandler = messageHandler
        this.errorHandler = errorHandler
    }
    openSocket = async () => {
        //Logic for opening up socket

        //Subscribe to socket events
        .subscribe(
            (x) => this.messageHandler(x),
            (err) => this.errorHandler(err),
            () => console.log("Observer got a complete notification"),
        )
   }
}

As you can see, I want to pass two callback functions to my above super-class - Respectively one for handling incoming messages, and another for handling eventual error events.

My sub-class looks as follows:

class Sub extends SocketBase {
    constructor(link) {
        super(this.messageHandler, this.errorHandler)
    }
    errorHandler = (err) => {
        //some logic
    }
    messageHandler = (message) => {
        //some logic
    }

}

Since the incoming messages are events, I thought passing a callback function to the super-class made sense. However, I realize that my sonarlint is complaining.

i.e.

'this' is not allowed before 'super()'.sonarlint(javascript:S3854)

It is however possible for me to define the callback function in my constructor arguments as follows:

super(function(message){console.log(message)}, function(error){console.log(error)})

Ofcause this is not what I want, for obvious reasons the above solution may get very messy.

Another solution would be for me to construct my base-class, but that would give me some undesired issues as well.. For example, I would have to do as follows:

this.socketBase = new SocketBase(this.messageHandler, this.errorHandler)

//Open socket (Not pretty) 
openSocket = () => {
    this.socketBase.openSocket() 
}

Conclusively, I want to understand how I should approach this problem?

Upvotes: 0

Views: 100

Answers (1)

connexo
connexo

Reputation: 56754

With your code example, there is no need to pass the functions, at all:

class SocketBase {
    openSocket = async () => {
        //Logic for opening up socket

        //Subscribe to socket events
        .subscribe(
            (x) => this.messageHandler(x),
            (err) => this.errorHandler(err),
            () => console.log("Observer got a complete notification"),
        )
   }
}

class Sub extends SocketBase {
    constructor(link) {
        super();
        //  do whatever you need to do with `link` parameter
    }
    errorHandler = (err) => {
        //some logic
    }
    messageHandler = (message) => {
        //some logic
    }
}

If for whatever strange reason you need the passing to the super class, here you go.

You can define constants and pass those to super, and by calling super, you already assign those to your instance this.

class Sub extends SocketBase {
  constructor(link) {
    const errorHandler = (err) => {
      // errorHandler Code here
    }
    const messageHandler = (msg) => {
      // messageHandler Code here
    }
    super(messageHandler, errorHandler)
  }
}

You can also work with closures here, but in that case remember to use regular functions and bind them in the superclass:

function errorHandler(err) {
  // errorHandler Code here
}
function messageHandler(msg) {
  // messageHandler Code here
}

class Sub extends SocketBase {
  constructor(link) {
    super(messageHandler, errorHandler);
  }
}

class SocketBase {
  constructor(messageHandler, errorHandler) {
    this.messageHandler = messageHandler.bind(this);
    this.errorHandler = errorHandler.bind(this);
  }
}

Upvotes: 1

Related Questions