如何同步运行 requestAnimationFrame()?

How to run requestAnimationFrame() synchronously?

所以我正在制作一个类似俄罗斯方块的小游戏,其中的方块会相互掉落、被破坏等。我正在通过 requestAnimationFrame() 制作 HTML5 canvas 动画。调用此方法是为了收集悬在半空中的方块,并顺畅地落下:

function dropTiles() {
    var tileArray = getFallingTiles();
    function step() {
        var finished = true;
        for (var index = 0; index < tileArray.length; ++index) {
            var currentTile = tileArray[index];
            if (currentTile.fallDepth > 0) {
                finished = false;
                currentTile.erase();
                currentTile.positionY -= 1;
                currentTile.fallDepth -= 1;
                currentTile.draw();
            }
        }
        if (!finished) {
            window.requestAnimationFrame(step);
        }
    }
    window.requestAnimationFrame(step);
}

这是调用上述方法的主要方法:

function doGameEvents() {
    setCanvasListeners(false);
    do {
        var comboFactor = 1;
        dropTiles();
        while (getGroups()) {
            score();
            dropTiles();
            ++comboFactor;
        }
        if (comboFactor == 1) {
            var newTile = getRandomTile();
            TILES.push(newTile);
            dropTiles();
        }
    } while (!hasMoves());
    setCanvasListeners(true);
}

一切正常,但我注意到一旦 dropTiles() 被调用,控制会立即转移到下一条指令,即使后者尚未完成(即 score() 仍然被调用悬在半空中)。

所以我的问题是:如何使 requestAnimationFrame() 同步并在控件退出我的 dropTiles() 方法之前完全完成?

你不知道。您将 drop 方法重写为 notify 当它完成时。最简单的:

function dropTiles(callback) {
    //...
    function step() {
        //...
        if (!finished) {
            window.requestAnimationFrame(step);
        }
        else
        {
            if(callback)callback();
        }
    }
    window.requestAnimationFrame(step);
}

所以现在当您调用 drop 时,您可以

drop(function(){
    //this code runs when drop is finished
});

如果您需要等待很多 drop 才能完成,您可以选择使用 Promises。 (提示:Promise 就在这里……你真的应该学习如何使用它们)。

function dropTiles() {
    return new Promise(function(resolve,reject){
        //...
        function step() {
            //...
            if (!finished) {
                window.requestAnimationFrame(step);
            }
            else
            {
                resolve();
            }
        }
        window.requestAnimationFrame(step);
    });
}

现在您可以:

drop().then(function(){
    //drop is finished
});

Promise.all([drop(), drop(), drop()]).then(function(){
    //all the drops finished
});