简体   繁体   中英

javascript function is not binding the 'this' when passed as a callback to the backend(node) using socket.io

One of my functions in the frontend is using ' this '.

function myFunction() {     
    ...     
    console.log(this);     
    ... 
}

I call it like this:

myFunction.call(objAsThis, param1, param2);

and everything is working as expected. But then I tried to pass this function to the backend(node.js) as a callback using socket.io :

Client

socket.emit("some event", param3, param4, myFunction);

Calling this function in node in the same way rendered some unexpected results.

Server

socket.on("some event", function(param3, param4, myCbFunction) {     
    ...     
    myCbFunction.call(someObject, param5, param6);     
    ... 
});

I expect to see the someObject object printed but instead I get the socket.io 's ' this ' printed. Same story if I try to use bind:

myCbFunction.bind(someObject)(param5, param6);

I even tried(out of curiosity) calling it with new , which should have created a new object, but it didn't. Outcome remained as before.

new myCbFunction(param5, param6);

I get the same result( socket.io 's this ) if I just console.log(this) inside the “some event” event handler on the server. So myCbFunction completely ignored the call , the bind or the new .

Can someone please explain what is going on? Why it's not binding this to the object I provide?

OK, I think I see a source of confusion.

When you register this on the server:

socket.on("some event", function(param3, param4, callback) {     
    ...
    callback(someArgs);
});

The point of callback() is to notify the client that you have received the message. It's referred to in the documentation as an ack function. This is NOT directly calling your client code. In fact, this callback function is something that socket.io provides and when you call it you're calling socket.io, not calling the client. Instead, you call this function provided by socket.io and when socket.io receives this function call it packages up a message and sends that message back to the client over the socket.io connection. You call that ack function on the server when you want to tell the client that you've received the original message.

Keep in mind that client and server are nearly always on separate computers miles apart (always at oppositive ends of a TCP socket). You can't directly call client code from the server.

The client socket.io code will receive that ack message (and any serializable arguments you sent with it) and then will call the client side ack function that you specified here:

socket.emit("some event", param3, param4, myFunction);

You do not control the this value when this ack function is called - it will be whatever socket.io sets it to (unless you declare it as an arrow function). But, instead of passing your actual function, you can use a stub function and then reattach the desired this value before calling your real function.

socket.emit("some event", param3, param4, function(...args) {
     myFunction.call(objAsThis, ...args)
});

This will then ignore the this value that the socket.io library passed to the callback and will attach the one you want. You could also use .bind() to do the same thing:

socket.emit("some event", param3, param4, myFunction.bind(objAsThis));

which is just another way of passing a stub function as shown in the prior code solution.

And, if this was in the lexical context, you could also use an arrow function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM