Reputation: 3679
I want to create a client-side function that can receive and execute arbitrary commands using client-side variables. I will be sending these functions from my server by using socket.io to send a JSON object containing an anonymous function which will be my command. It looks something like the following:
//client side
socket.on('executecommand', function(data){
var a = "foo";
data.execute(a); //should produce "foo"
});
//server side
socket.emit('executecommand', {'execute': function(param){
console.log(param);
}});
Yet, when I tried it out, the client side received an empty json object (data == {}
), then threw an exception because data contained no method execute. What is going wrong here?
Upvotes: 6
Views: 5286
Reputation: 371
Here's how I did this eventually.
Have the functions in a common place (const.js
here) and send the key.
// const.js
const FNS = {
timer: { exec: t => console.log(`You have ${t} seconds!`) },
}
// server
const FNS_KEYS = Object.keys(CONST.FNS).reduce((m,k) => (m[k]=k,m), {})
socket.emit('execute', FNS_KEYS.timer)
// client
socket.on('execute', key => CONST.FNS[key]?.exec(30))
Upvotes: 0
Reputation: 123533
JSON doesn't support the inclusion of function
definitions/expressions.
What you can do instead is to define a commands
object with the function
s you need and just pass a commandName
:
// client-side
var commands = {
log: function (param) {
console.log(param);
}
};
socket.on('executecommand', function(data){
var a = 'foo';
commands[data.commandName](a);
});
// server-side
socket.emit('executecommand', { commandName: 'log' });
You can also use fn.apply()
to pass arguments and check the commandName
matches a command with in
:
// client-side
var commands = { /* ... */ };
socket.on('executecommand', function(data){
if (data.commandName in commands) {
commands[data.commandName].apply(null, data.arguments || []);
} else {
console.error('Unrecognized command', data.commandName);
}
});
// server-side
socket.emit('executecommand', {
commandName: 'log',
arguments: [ 'foo' ]
});
Upvotes: 10
Reputation: 1692
You can't send literal JavaScript functions and expect it to work. You'll need to stringify the function first (i.e put it within a set of quotes), then eval the string on the client side.
Upvotes: 4