0

I'm currently playing around with coffeescript and websockets using nodejs.
I created a class SocketHandler for managing websocket clients:

class SocketHandler
    constructor: (@server) ->
        @server.on "connection", @onClientConnect   

    onClientConnect: (socket) ->
        console.log "client connected"
        socket.on "close", @onClientDisconnect

    onClientDisconnect: (code, message) ->
        console.log "client disconnected"

ws = require "ws"
server = ws.Server { port: 8080 }
sockethandler = new SocketHandler server

When I run the script and a client connects I get the following error message:

client connected
events.js:210
    throw new TypeError('listener must be a function');
    ^

TypeError: listener must be a function
[...]

I have no clue why this happens. In my view I'm passing a function reference to socket.on as the second parameter.

I tried to investigate further and tried to output onClientDisconnect to see what type it has.
So I changed

onClientConnect: (socket) ->
    console.log "client connected"
    socket.on "close", @onClientDisconnect

to

onClientConnect: (socket) ->
    console.log "client connected"
    console.log @onClientDisconnect
    socket.on "close", @onClientDisconnect

resulting in getting an undefined value as output.

Now I'm really confused and I think I'm missing something fundamental at how the language works.
Can anyone of you help me out?

2
  • 1
    Is that your real indentation? Shouldn't onClientConnect and onClientDisconnect be indented a level so that they're part of SocketHandler? Commented Feb 15, 2016 at 20:13
  • @muistooshort: oh missed that. thanks for the hint, corrected it. Commented Feb 15, 2016 at 20:44

1 Answer 1

1

Reminder: @onClientConnect is shorthand for this.onClientConnect. this is exactly the problem here. The context of a function call (what this is inside a function) is determined at call time in Javascript. When you pass a function, the receiver receives it "without context", and when invoked as such, this won't refer to the this you're thinking/want/expect.

Long story short: you need to bind this to your function, so the @ in @onClientDisconnect actually refers to your class instance:

@server.on "connection", @onClientConnect.bind @

Alternative in CoffeeScript (using a context-bound fat arrow callback):

@server.on "connection", => @onClientConnect()

Also see How to access the correct `this` context inside a callback?

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

Comments

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.