3

Now I'm trying to implement Unity Webgl with jslib. I'm so confused about how to call method in another method's function. I want to call method Recv when message was coming (ws.onmessage). But, it show "TypeError: this.Recv is undefined". Could you please help me figure out this source?
Thank you !!!!!

Here's my source code

var ws = null;
var init_url = "";
var received_msg = "";
var error_msg = "";

var WebsocketLib = {
Hello: function(){
    window.alert("Hello,world!");
},
InitSocket: function(url){
    init_url = Pointer_stringify(url);
    console.log("InitWebSocket: "+init_url);
    ws = new WebSocket(init_url);
    ws.onopen = function(evt){ 
            console.log("Connect");
            isConnected = false;
            ws.send("hello");
        }; 
    ws.onclose = function(evt) { 
            console.log("Close");
            isConnected = false;
        }; 
    ws.onmessage = function(evt) {
            received_msg = evt.data;
            console.log("[recv] "+received_msg);
            this.Recv.call(this);
        }; 
    ws.onerror = function(evt) {
            error_msg = evt.data;
            console.log("[error] "+error_msg);
            this.Error.call(this);
        };
},
Recv: function(){
    console.log("[recv] "+received_msg);
    var buffer = _malloc(received_msg.length + 1);
    writeStringToMemory(returnStr, buffer);
    return buffer;
},
Error: function(){
    console.log("[error] "+error_msg);
    var buffer = _malloc(error_msg.length + 1);
    writeStringToMemory(error_msg, buffer);
    return buffer;
}
}
Ar Aui
  • 384
  • 1
  • 7
  • 17

2 Answers2

2

Inside of ws.onmessage this will refer to ws (as we're inside a method of ws) and not WebsocketLib.

However, inside Initsocket, where you define the handlers, this would correctly (in the sense that this is what you want) refer to the WebsocketLib object, so you can create a bound function to bind the outer this value to be used as this inside the event handler, like this:

ws.onmessage = function(evt) {
        received_msg = evt.data;
        console.log("[recv] "+received_msg);
        this.Recv.call(this);
}.bind(this); 
doldt
  • 4,312
  • 3
  • 19
  • 36
2

in JavaScript the value of this behaves differently than in other languages. Its value depends on how the function is called. You can read more about it in the Mozilla MDN page.

To solve your specific problem you can:

InitSocket: function(url){
    var that = this;                                  // [1]
    init_url = Pointer_stringify(url);
    console.log("InitWebSocket: "+init_url);
    ws = new WebSocket(init_url);
    ws.onopen = function(evt){ 
            console.log("Connect");
            isConnected = false;
            ws.send("hello");
        }; 
    ws.onclose = function(evt) { 
            console.log("Close");
            isConnected = false;
        }; 
    ws.onmessage = function(evt) {
            received_msg = evt.data;
            console.log("[recv] "+received_msg);
            that.Recv.call(that);                     // [2]
        }; 
    ws.onerror = function(evt) {
            error_msg = evt.data;
            console.log("[error] "+error_msg);
            that.Error.call(that);                    // [2]
        };
},

In line 1 I bind the this variable to a custom variable that I decided to call that (but you can call it as you want). Then in line 2 I used that instead of this.

Inside the ws.onmessage function the value of this is not referring to the instance of WebsocketLib, so you need to use this "trick" and access the right this value using the one saved in the closure, inside the value of that.

Andrea
  • 2,800
  • 1
  • 15
  • 24
  • Thank you for your answer :) – Ar Aui Aug 04 '15 at 07:41
  • I am a learner. So I suppose that `this.Error.call(this)` won't work neither, right? – iplus26 Aug 04 '15 at 07:50
  • Yes, for the same reason `this.Error.call(this)` does not work, you have to change `this` to `that`. For a better understanding of `this` you can read the MDN article I suggested and [this StackOverflow](http://stackoverflow.com/a/3127440/2009013). – Andrea Aug 04 '15 at 07:53
  • Just edited my answer to correct "this.Error.call(this)" to "that.Error.call(that)" and "that.Recv.call(this);" to "that.Recv.call(that);". You need to change the `this` inside the "call(this)" for the same reason I explained. Otherwise, the "Recv" and "Error" function calls will not be bind to the correct object instance. – Andrea Aug 04 '15 at 07:58