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: Не можах да намеря никакви споменавания на библиотека с нибъли за възел. И ако сте имали предвид пъргав, това не е това, което имах предвид, тъй като все още ви принуждава да извършвате контролен поток с помощта на библиотека вместо съществуващи 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 се опитвате да прочетете плейъра, но той не е зададен, тъй като обратното извикване не е извикано. Не забравяйте, че имате работа с асинхронно програмиране. Опитайте да използвате 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