承诺说他们完成了,但他们没有?

Promises say they are done when they are not?

我有一个浏览器游戏,它必须在开始前加载一些东西。我把所有的加载都封装成两个promise。

var promise1 = new Promise(function(resolve, reject) { ...loading stuff here... resolve() });
var promise2 = new Promise(function(resolve, reject) { ...loading stuff here... resolve() });

然后我在下面放了一个启动游戏循环的函数

Promise.all([promise1, promise2]).then(setInterval(GameLoop, time));

编辑:在上面的代码中添加 () => 并没有解决问题。

问题是,虽然一切都启动并运行良好,但在加载所有内容之前它仍然会抛出四帧错误。我认为 promises 应该等到它们内部的代码完成它的事情。

我不太确定出了什么问题。可能我错过了关于 javascript 的一些基本知识。浏览器没有抛出任何错误,只是它在开始时找不到 4 - 5 帧的变量。

原代码:

//{ DATA
    var promise_loadClient = new Promise ((resolve, reject) => {
    
        //{ LOAD DISPLAY OBJECTS
            //Objects required for displaying elements of the game
            window.canvasb = document.getElementById('screen_board');
            window.ctxb = canvasb.getContext('webgl',{ alpha: false });
            ctxb.clearColor(100.0, 0.0, 0.0, 1.0);
            canvasb.width = window.innerWidth;
            canvasb.height = window.innerHeight - element_navbar.offsetHeight;
            
            window.pixi_app = new PIXI.Application({
                view: canvasb,
                antialias: true,
                width: window.innerWidth,
                height: window.innerHeight - element_navbar.offsetHeight
            });
            
            window.graphics = new PIXI.Graphics();      
            
            window.canvas = document.getElementById('screen_entities');
            window.ctx = canvas.getContext('2d',{ alpha: true });
                //ctx.imageSmoothingEnabled = false;
                //ctx.webkitImageSmoothingEnabled = false;
                //ctx.mozImageSmoothingEnabled = false;
                ctx.translate(0.5,0.5);

        //}

        //{ GAME LOOP VARS
            window.step = 1; //frame time target (ms)
            window.timein = 0  //vars for recording loop time
            window.timeout = 0;
            window.averageTimes = [];
        //}

        //{ LOAD TEXT DISPLAY OBJECTS
            window.element_timer = document.getElementById('timer'); //Time repurposed as debug window
                   element_timer.style.left = -1000; //hide the debug window
            window.element_highscores = document.getElementById('highscores'); //High score display
            window.element_moveindicator = document.getElementById('moveindicator'); // Moves left indicator
        //}
    
        window.mouseX = 0; window.mouseY = 0; //TODO: embed in playerview
        resolve();
    });
//}

var promise_loadManager = new Promise ( (resolve, reject) => {
    //{ DATA LOAD

        //Images
        window.texture_blackrook = new PIXI.Texture.from('../assets/images/rookblack.png');
        window.texture_blackpawn = new PIXI.Texture.from('../assets/images/pawnblack.png');
        window.texture_blackking = new PIXI.Texture.from('../assets/images/kingblack.png');
        window.texture_blackqueen = new PIXI.Texture.from('../assets/images/queenblack.png');
        window.texture_blackbishop = new PIXI.Texture.from('../assets/images/bishopblack.png');
        window.texture_blackknight = new PIXI.Texture.from('../assets/images/knightblack.png');
        
        window.texture_whiterook = new PIXI.Texture.from('../assets/images/rookwhite.png');
        window.texture_whitepawn = new PIXI.Texture.from('../assets/images/pawnwhite.png');
        window.texture_whiteking = new PIXI.Texture.from('../assets/images/kingwhite.png');
        window.texture_whitequeen = new PIXI.Texture.from('../assets/images/queenwhite.png');
        window.texture_whitebishop = new PIXI.Texture.from('../assets/images/bishopwhite.png');
        window.texture_whiteknight = new PIXI.Texture.from('../assets/images/knightwhite.png');
        
        window.texture_greyrook = new PIXI.Texture.from('../assets/images/rookgrey.png');
        window.texture_greypawn = new PIXI.Texture.from('../assets/images/pawngrey.png');
        window.texture_greyking = new PIXI.Texture.from('../assets/images/kinggrey.png');
        window.texture_greyqueen = new PIXI.Texture.from('../assets/images/queengrey.png');
        window.texture_greybishop = new PIXI.Texture.from('../assets/images/bishopgrey.png');
        window.texture_greyknight = new PIXI.Texture.from('../assets/images/knightgrey.png');
        
        window.texture_whitearrow = new PIXI.Texture.from('../assets/images/arrow01.png');
        
        window.texture_tilelight = PIXI.Texture.from('../assets/images/tilelight.bmp');
        
        //{OLD IMAGES - TO BE REPLACED SOON
        window.img_blackking = new Image(1,1); img_blackking.src = '../assets/images/kingblack.png';
        window.img_blackqueen = new Image(1,1); img_blackqueen.src = '../assets/images/queenblack.png';
        window.img_blackbishop = new Image(1,1); img_blackbishop.src = '../assets/images/bishopblack.png';
        window.img_blackrook = new Image(1,1); img_blackrook.src = '../assets/images/rookblack.png';
        window.img_blackknight = new Image(1,1); img_blackknight.src = '../assets/images/knightblack.png';
        window.img_blackpawn = new Image(1,1); img_blackpawn.src = '../assets/images/pawnblack.png';
        
        window.img_whiteking = new Image(1,1); img_whiteking.src = '../assets/images/kingwhite.png';
        window.img_whitequeen = new Image(1,1); img_whitequeen.src = '../assets/images/queenwhite.png';
        window.img_whitebishop = new Image(1,1); img_whitebishop.src = '../assets/images/bishopwhite.png';
        window.img_whiterook = new Image(1,1); img_whiterook.src = '../assets/images/rookwhite.png';
        window.img_whiteknight = new Image(1,1); img_whiteknight.src = '../assets/images/knightwhite.png';
        window.img_whitepawn = new Image(1,1); img_whitepawn.src = '../assets/images/pawnwhite.png';
        
        window.img_greyking = new Image(1,1); img_greyking.src = '../assets/images/kinggrey.png';
        window.img_greyqueen = new Image(1,1); img_greyqueen.src = '../assets/images/queengrey.png';
        window.img_greybishop = new Image(1,1); img_greybishop.src = '../assets/images/bishopgrey.png';
        window.img_greyrook = new Image(1,1); img_greyrook.src = '../assets/images/rookgrey.png';
        window.img_greyknight = new Image(1,1); img_greyknight.src = '../assets/images/knightgrey.png';
        window.img_greypawn = new Image(1,1); img_greypawn.src = '../assets/images/pawngrey.png';
        
        window.img_whitearrow = new Image(1,1); img_whitearrow.src = '../assets/images/arrow01.png';
        //}
        
        //Sounds
        window.sound_swipe = new Audio("../assets/sounds/chess_swipe.mp3");
        window.sound_ticking = new Audio("../assets/sounds/chess_ticking3.mp3");
        window.sound_turnbell = new Audio("../assets/sounds/chess_softbell.mp3");
        window.sound_swish = new Audio ("../assets/sounds/chess_swish.mp3");
        window.sound_tap = new Audio ("../assets/sounds/chess_tap.mp3");
        
        
        //Fetch elements
        window.element_timer = document.getElementById('timer'); //TEMP RENDER TIMER
        window.element_highscores = document.getElementById('highscores'); //TEMP RENDER TIMER
        window.element_moveindicator = document.getElementById('moveindicator');
        
        // Env
        window.manager = new GameManager ("inactive", Date.now(), 10000); // Create manager, let it be altered later in the script


    //}

    //{ CONNECT TO SERVER
        
        
        window.socket = io('//localhost:3001'); 
    //}

    //{ PLAYER INFO
        //Information about the player's id and game choices.
        
        //{ Get room request from URL and send to server!
            window.roomRequest = window.location.search.split("=")[1];
            socket.emit("requestboard", parseInt(roomRequest));
        //}
        
        //{ Get nickname from cookies, if not there ask for one. To be replaced by user auth interface
            window.nickname = CookieIO.GetCookieByName("nickname");
            if(nickname == null)
            {
                nickname = window.prompt("Please enter a nickname. Max 16 characters. (To change nickname, you'll need to clear cookies for this site)");
                nickname = nickname.substring(0,16);
                CookieIO.SetCookieByName("nickname", nickname, 365); 
            }
        //}

    //}

    //{ SERVER LOAD
        //{ Setup game - create board from server details and recieve pieces information
            socket.on('newboard', function(msg){
            
                console.log("SERVER: New Board");

                //Create board object from server
                window.manager = new GameManager("inactive",0,0);
                window.board = new ChessBoard(msg.chessBoard.radius,
                                       msg.chessBoard.randomRange,
                                       msg.chessBoard.randomLimit,
                                       new HexColor(msg.chessBoard.colorLight),
                                       new HexColor(msg.chessBoard.colorDark),
                                       msg.chessBoard.shading_radius,
                                       msg.chessBoard.shading_innerStop,
                                       msg.chessBoard.shading_outerStop,
                                       msg.chessBoard.shading_innerAlpha,
                                       msg.chessBoard.shading_outerAlpha
                                       );
                //Precalculate as may variables as possible.
                window.boardSprites = new ObjectRegister(board.radius * 2, board.radius * 2);
                window.boardViable = new ObjectRegister(board.radius*2, board.radius * 2);          
                    PreCalcBoardSprites(boardSprites, board, texture_tilelight);
                    PreCalcTileRNGViable(boardViable);
                
                    
                
                window.client = new PlayerData(msg.playerID, msg.roomName);
                client.nickname = nickname;
                
                //and create a way to view it with player!
                window.player = new PlayerView(board.radius, board.radius,4);
                    player.viewportBoardMaxX = board.radius * 2;
                    player.viewportBoardMaxY = board.radius * 2;
                    player.viewportMoved = true;
                        
                window.pieces = new ChessPieceRegister(board.radius * 2, board.radius * 2);
                window.deadPieces = [];
                for(i = 0; i < msg.chessPieceRegister.length; i++){     
                    pieces.NewPiece(parseInt(msg.chessPieceRegister[i].positionX),
                                    parseInt(msg.chessPieceRegister[i].positionY), 
                                    msg.chessPieceRegister[i].type,
                                    msg.chessPieceRegister[i].team,
                                    msg.chessPieceRegister[i].playerID);
                }

                isLoaded = true; //Once these things are loaded, then the game should be good to go.
                //A board will display and the player can look around. 
            });
            socket.on('newplayerpieces', function (msg){
                console.log("SERVER: newplayerpieces");
                let tempPiece = null;
                for(i = 0; i < msg.length; i++)
                {   
                    tempPiece = pieces.GetPiece(parseInt(msg[i].positionX), parseInt(msg[i].positionY));
                    
                    if(tempPiece != null)
                    {
                        oldX = tempPiece.oldPositionX;
                        oldY = tempPiece.oldPositionY;
                        displayX = tempPiece.displayPositionX;
                        displayY = tempPiece.displayPositionY;
                        pieces.NewOldPiece(parseInt(msg[i].positionX),
                                                      parseInt(msg[i].positionY),
                                                      msg[i].type,
                                                      msg[i].team,
                                                      msg[i].playerID,
                                                      oldX,
                                                      oldY,
                                                      displayX,
                                                      displayY);
                    }
                    else
                    {
                        pieces.NewPiece(parseInt(msg[i].positionX), parseInt(msg[i].positionY), msg[i].type, msg[i].team, msg[i].playerID);
                    }
                }
                
                client.pieces = pieces.GetPiecesByID(client.playerID);
                kings = pieces.GetPiecesByIDType(client.playerID, "king");
                client.king = kings[0]; //fuck it, we'll only have the one king
                client.team = client.king.team;
                
                player.positionX = client.king.positionX; //Change to a lerp
                player.positionY = client.king.positionY;

                isLoadedPieces = true;

            }); 
        //}
    //}

    //{ SERVER IO
        //{ Message from server.
            socket.on('messagefromserver', function (msg){
            msgs = msg.split('/');
            
            if (msgs[0] == "alert"){
                window.alert(msgs[1]);
            } else {
                console.log("SERVER: Message from server: " + msgs[1]);
            }
        });
        //}

        //{ Game Management (turns)
            socket.on('newturn', function(msg){
            console.log("SERVER: new turn: " + msg + "localnumber: " + (manager.turnNumber + 1));
            //sound_turnbell.volume = 0.5;
            //sound_turnbell.play();
            
            msgs = msg.split("/");
            
            manager.turnStart = Date.now();
            manager.turnAge = parseInt(msgs[0]);        //0, usually
            manager.turn = msgs[1];         //Color
            manager.gameState = msgs[2];    //Active
            manager.turnTime = msgs[3];     //How long in ms (5000)
            manager.turnTimeMax = msgs[3];  // "
            manager.movesLeft = parseInt(msgs[4]) + Math.floor(MyMath.Clamp(-16 + client.pieces.length, 0 ,50) / 4);
            //viewport.viewportMoved = true;
            if(client.king != null) manager.actualScore ++;
            
            
            manager.turnNumber ++;
            
        });
        //}

        //{ Deal with player interactions
            socket.on('newmove', function(msg){
                console.log("SERVER: new move: " + msg);

                sound_swipe.play();
                
                
                moves = msg.split("/");
                let oldPiece = pieces.GetPiece(moves[3], moves[4]);
                piece = pieces.GetPiece(parseInt(moves[1]),parseInt(moves[2]));
                let killerPiece = piece;
                piece.oldMoveGizmoEnd = Date.now() + (manager.turnTimeMax * 3);
                piece.oldMoveGizmoStart = Date.now();
                piece.hasMovedThisTurn = true;
                pieces.MovePiece(piece, parseInt(moves[3]),parseInt(moves[4]));
                if(piece.playerID == client.playerID) manager.Move();


                
                if(oldPiece != null) {
                    deadPieces.push(new DeadPiece(oldPiece, 0, killerPiece));
                    manager.actualScore += oldPiece.rank;
                }
                    
                client.pieces = pieces.GetPiecesByID(client.playerID);
                player.viewportMoved = true;
            });
            socket.on('removeplayer', function(msg){
                console.log("SERVER: Remove Player: " + msg);
                pieces.RemovePiecesById(msg);
                player.viewportMoved = true;
            }); 
            socket.on('killplayer', function(msg){
                console.log("SERVER: Killplayer: " + msg);
                msgs = msg.split("/");
                pieces.KillPlayer(msgs[0], msgs[1], msgs[2]);
                player.viewportMoved = true;
                client.pieces = pieces.GetPiecesByID(client.playerID);
            });
            socket.on('changeteamofpiece', function (msg){
                
                    console.log("SERVER: change team of piece", msg);
                    msgs = msg.split("/");
                    pieces.ChangeTeamOfPiece(msgs[0], msgs[1], msgs[2], msgs[3]);
                    player.viewportMoved = true;
                });
            socket.on('newscores', function(msg) {
                console.log("SERVER: newscores: ", msg);
                msg.sort(function(a, b){return b.score-a.score});   
                manager.allScoresNew = msg;
                
            });
        //}

    //}
    
    window.gameInitialized = true
    resolve();
});

Promise.all([promise_loadClient, promise_loadManager]).then( () => setInterval(GameLoop, step) );

setInterval 正在立即执行。尝试将该代码放在传递给 .then:

的函数中
Promise.all([promise1, promise2]).then(() => setInterval(GameLoop, time));

我误解了承诺。

在 promise 内的异步函数完成之前调用 Resolve,这反过来意味着 promise 比预期提前完成。

基本上我之前的每一个承诺都是:

var promise1 = new Promise ((resolve, reject) => {
    
    function irrelivantfunction1 (){
        // things
    }
    
    async function importantfunction1 (){
        // things
    }
    
    function irrelivantfunction2 (){
        // things
    }
    
    async function importantfunction2 (){
        // things
    }
    resolve()   

})

但应该是:

function irrelivantfunction1 (){
    // things
}

var promise1 = new Promise ((resolve, reject) => {
    async function importantfunction1 (){
        // things
        resolve();
    }
});

function irrelivantfunction2 (){
    // things
}

var promise2 = new Promise ((resolve, reject) => {
    async function importantfunction1 (){
        // things
    resolve()   
    }
});

每个异步函数一个。并且,最后这样解决:

Promise.all([promise1, promise2]).then(() => setInterval (GameLoop, time));

此外,将'() =>'添加到设置的间隔,否则它将立即运行。