It's not that it becomes undefined outside of the function but it's most likely not defined yet. You didn't show how you want to access it outside of the function but if it's anything like this:
var clientId;
socket.on('clientId', function(data){
clientId = data;
});
console.log(clientId);
then the console.log line will be run before clientId = data so it is the same variable, it's just not defined yet.
You need to access that variable from your socket.on handler, or from some function that is run by that handler, or after that handler has already been run.
It's hard to tell anything more specific since you didn't say how do you want to access the variable and what do you want to do with it. You can see my example that I put on GitHub that does something like that to see if that could help you:
It looks like this:
var l = document.getElementById('l');
var log = function (m) {
var i = document.createElement('li');
i.innerText = new Date().toISOString()+' '+m;
l.appendChild(i);
}
log('opening socket.io connection');
var s = io();
s.on('connect_error', function (m) { log("error"); });
s.on('connect', function (m) { log("socket.io connection open"); });
s.on('message', function (m) { log(m); });
Here, the log function is called from within the handler so that it is guaranteed to be called after the message has already been passed. The data is passed as an argument to that function but it could use a global variable as well.
Update
Here is a simpler example:
var clientId;
socket.on('clientId', function (data) {
clientId = data;
clientReady();
});
function clientReady() {
// you can access it here:
console.log(clientId);
}
Here you can access your variable in the clientReady function which is outside of the on handler. Think of it like you would about the window.onload handler:
window.onload = function() {
// ...
};
or $(document).ready() in jQuery:
$(document).ready(function () {
// ...
});
It is a piece of code that gets called on a certain moment to guarantee that everything that you need is ready.
Another example using a promise:
var clientIdPromise = new Promise(function (resolve, reject) {
socket.on('clientId', function (data) {
resolve(data);
});
});
// now everywhere in your code you can access it as:
clientIdPromise.then(function (clientId) {
// you have access to clientId here
});
Or shorter, using the fat arrow notation:
var clientIdPromise = new Promise(
(res, rej) => socket.on('clientId', data => res(data));
// and somewhere else:
clientIdPromise.then(clientId => {
// you have access to clientId here
});