Использование обещаний и asyn c с socket.io не возвращает ожидаемых результатов - PullRequest
0 голосов
/ 13 апреля 2020

Я очень новичок в обещаниях. Мне нужен мой сервер для ожидания сокетных подключений от внешнего API и от подключений клиентов браузера. Внешний API-интерфейс отправляет на сервер несколько объектов (в данном примере 4), которые принимаются в качестве обещания и вызывают функцию, которая ожидает обещание. Для каждого объекта, полученного обещанием, клиент браузера может установить соединение (обещание) и присоединиться к игре.

У меня есть функция, которая должна ждать заполнения переменных этими двумя обещаниями. Он успешно ожидает внешних объектов API, но никогда не получает обещание указать, что правильное число клиентов установило соединения.

Я обернул сокет прослушиванием внешних объектов API в обещание, так как оно будет отправлено только один раз. Я также вызываю функцию, которая обрабатывает два обещания здесь, поскольку она, кажется, не работает где-либо еще.

//HANDLER FOR GAME OBJECT SENT FROM MAX API
const maxPromise = new Promise ((resolve) => {
    socket.on("dictData", async (data)=>{
        try {
            let {songName, level, imageArr} = data;
            let [imageObj] = imageArr;
            gameVars.songName = songName;
            gameVars.level = level;
            let gameObject = {};
            for (let obj in imageArr) {
            let objectId = imageArr[obj].name;
            gameObject.objectId = objectId;
            gameObject.path = imageObj.path;
            // gameObject.files = imageObj.imagePath;
            gameState.totalServerCount ++;
            gameState.serverList.push({gameObject});
            }
            resolve(gameState.serverList) //resolve the promise with the array of objects
            sendData()
        } 
        catch (e) {
            console.error(e)
        }
    });
});

Я также обернул прослушиватель req клиента в обещание, потому что после бесчисленных попыток вложить обещание внутрь это было единственное решение, которое не вернуло фактический сокет как обещание, поэтому я считаю, что это, вероятно, самое близкое решение для меня.

Это обещание должно разрешаться только при одинаковом количестве клиентских подключений. поскольку есть объекты сервера, полученные в первом обещании. Я тестирую, просто подключив 4 открытые вкладки к localhost: 3000.

//HANDLER FOR CLIENT REQUEST TO JOIN GAME
const playerPromise = new Promise ((resolve, reject) => {
    socket.on('joinGame', async () => {
        try {
            gameState.totalPlayerCount++;
            gameState.playerList.push(socket.id)
                switch (true) {
                    case gameState.totalPlayerCount < gameState.totalServerCount : 
                        console.log("Not enough players", gameState.totalPlayerCount)
                        break; 
                    case gameState.totalPlayerCount <= gameState.totalServerCount :
                        console.log("Counts are equal", gameState)
                        readyPlayers = true; 
                        resolve(gameState.playerList)
                        break; 
                    case gameState.totalServerCount == 0 :
                        console.log("Server not ready", gameState)
                        break; 
                    default : 
                        console.log("Too many players", gameState.totalPlayerCount)
                        reject("Too many players", gameState.playerList)
                }
        }
        catch(e) {
            console.error(e);
        }
    })
})

Функция sendData () регистрирует 1-й и 2-й тесты на консоли, но не 3-й.

    async function sendData() {
        try {
            console.log("TEST1")
            const dataMax = await maxPromise;
            console.log("TEST2", dataMax)
            const dataPlay = await playerPromise;
            console.log("TEST3", dataPlay)
            for (var key in await dataPlay) {
                io.to(dataPlay[key]).emit('gameData', dataPlay[key]);
            }
        }
        catch(e) {
            console.error(e)
        }
    };

Я просматривал все другие подобные посты по stackoverflow и онлайн, но не могу найти никакого решения для этого или где я ошибаюсь. Я также разработал вышеупомянутое решение с минимальным знанием socket.io и обещаний, так что есть лучший / более чистый способ сделать выше, пожалуйста, дайте мне знать.

РЕДАКТИРОВАТЬ: это мое текущее решение, использующее только одно обещание, но теперь обещание не заполняется вообще в функции отправки:

//HANDLER FOR GAME OBJECT SENT FROM MAX API
const maxPromise = new Promise ((resolve) => {
    socket.on("dictData", async (data)=>{
        try {
            let {songName, level, imageArr} = data;
            let [imageObj] = imageArr;
            gameVars.songName = songName;
            gameVars.level = level;
            let gameObject = {};
            for (let obj in imageArr) {
            let objectId = imageArr[obj].name;
            gameObject.objectId = objectId;
            gameObject.path = imageObj.path;
            gameState.totalServerCount ++;
            gameState.serverList.push({gameObject});
            }
            resolve(gameState.serverList) 
        } 
        catch (e) {
            console.error(e)
        }
    });
});
    async function sendData(playerData) {
        try {
            console.log("TEST1")
            const dataMax = await maxPromise;
            console.log("TEST2")
            for (var key in await playerData) {
                io.to(playerData[key]).emit('gameData', dataMax);
            }
        }
        catch(e) {
            console.error(e)
        }
    };

SendData () вызывается в обработчике сокета клиента, который просто передает массив соединений как playerData. «TEST2» никогда не регистрируется.

Учитывая, что обещание maxPromise является глобальным, разве оно не сможет получить доступ к его значению?

...