JavaScript, node.js ждет ответа socket.on, прежде чем продолжить

Мне нужно получить информацию с сервера на стороне клиента. Итак, на стороне сервера я получил это при первом подключении клиента:

socket.on('adduser', function(username){
    // misc code, where i set num_player and whatnot
    socket.emit('confirmauth', socket.id, socket.num_player, function(data){
         console.log(data)
    });
    // code
}

и на стороне клиента я получил это:

var current_player;
socket.on('confirmauth', function(id, username, num, callback) {

    current_player = new Player(username,id, num);

    console.log(current_player.id); // works
    console.log(current_player.num); //works
    callback('ok i got it');
});

console.log(current_player.id); //undefined
console.log(current_player.num); //undefined

моя проблема в том, что вне сокета вкл, плеер не определяется. Кажется, что javascript не ждет, пока мой сокет получит данные, прежде чем продолжить.

Я попытался обернуть socket.on в $.when done, но это не сработало. Я пытался сделать обратный вызов, но я думаю, что, возможно, не очень хорошо понял, как он должен работать. Так что если кто-то из вас захочет мне помочь, буду благодарен

Спасибо за ваши ответы.


person user3597823    schedule 22.05.2014    source источник


Ответы (3)


Если вы помещаете переменную current_player вне обратного вызова on в попытке return сделать это, альтернативой является получение вашей собственной функцией обратного вызова.

function getPlayer(onDone){
    socket.on('confirmauth', function(id, username, num, callback) {
        var current_player = new Player(username,id, num);
        onDone(current_player);
    });
}

И вместо того, чтобы делать

var player = getPlayer();
//...

Вы делаете

getPlayer(function(player){ 
    //...
});

Это отстой, что «обратная связь» немного заразительна в Javascript, но такова жизнь, пока все не начнут вместо этого использовать генераторы.

person hugomg    schedule 22.05.2014
comment
вот почему nibble существует для nodejs - person Luis Masuelli; 22.05.2014
comment
@LuisMasuelli: я не смог найти никаких упоминаний о библиотеке фрагментов для node. И если вы имели в виду шустрый, это не то, что я имел в виду, поскольку он по-прежнему заставляет вас выполнять поток управления с использованием библиотеки вместо существующих функций JS, таких как циклы while или try-catch. См. это. . - person hugomg; 22.05.2014
comment
возможно неправильное имя. позвольте мне проверить это еще раз... - да, вы правы. это в любом случае отстой, но это предостережение асинхронного программирования - person Luis Masuelli; 22.05.2014
comment
и в getPlayer(function(player) как я могу предоставить доступ к player везде в коде? - person user3597823; 22.05.2014
comment
@ user3597823: Что ты имеешь в виду под везде? По сути, идея состоит в том, что весь код, обращающийся к проигрывателю (представленному //...), должен будет перемещаться внутри обратного вызова. Если player была какой-то глобальной переменной, вы также можете инициализировать ее из обратного вызова, но вам нужно убедиться, что код, использующий BLOBAL, запускается только после инициализации: getPlayer(function(p){ player = p; startGame(); }) - person hugomg; 23.05.2014

Это связано с тем, что socket.on запускается с обратным вызовом и находится в обратном вызове, где установлен игрок. однако после вызова socket.on вы пытаетесь прочитать плеер, но он не устанавливается, так как callback не вызывался. Помните, что вы имеете дело с асинхронным программированием. Попробуйте использовать nibble, чтобы связать этот код после обратного вызова.

Помните: socket.on и многие другие обработчики сокетов - и даже многие другие обработчики событий (например, jquery) - НЕ ДОЛЖНЫ ждать, пока событие произойдет, поэтому вы должны мыслить асинхронно.

Возьмите этот пример:

  1. Вы вызываете socket.on во время подключения сокета (подключение занимает 3 секунды, так как, например, клиент находится за Tor). socket.on назначает обработчик событий (это единственное, что он делает, так как он работает для 11 или более событий, которые у него есть, таким же образом).
  2. Вы получаете доступ к плееру.

Но точка 1 не занимает 3 секунды, так как это просто назначение - соединение - это то, что устанавливается за 3 секунды. В этом смысле у вас есть неопределенная (фактически: неназначенная) переменная.

person Luis Masuelli    schedule 22.05.2014

Все эти операции являются асинхронными, поэтому лучше избегать глобальных переменных и сохранения состояния, насколько это возможно.

Тем не менее, пусть ваш обратный вызов перенесет вновь созданный объект Player туда, куда ему нужно — например, в реестр игроков? - и транспортировать его таким образом.

callback(current_player)

Оттуда вы можете поместить его в глобально доступный объект по своему усмотрению, например, если вы используете Backbone или на стороне сервера есть что-то, отслеживающее текущих пользователей.

person Gauss156    schedule 22.05.2014