RequestAnimationFrame只执行一次

时间:2016-06-14 11:59:35

标签: javascript jquery html5 gamepad

背景资讯: 我正在尝试使用ElectronJS进行申请。后端是一个python webserver,它在电子启动的同时启动。

我将python webserver称为“后端”,将ElectronJS称为“前端”。

问题: 动画帧需要执行对执行系统进程的python webserver的回调。此时游戏手柄按钮被多次注册并多次向后端执行请求。

所需行为: 我想要的是requestanimationframe不响应游戏手柄的连续按键直到功能完成。

我尝试了什么: 下面我有两个我试过的代码示例。还有很多我尝试过,但不记得了。有没有人能像我所描述的那样解决我的问题,或者是一种获得所需行为的方法?

我尝试的代码示例

 var respondToButton = true;

function scanInput()
{

    var gp = false;

    if (navigator.getGamepads()[0]) {
        gp = navigator.getGamepads()[0];

        if (respondToButton){

            if(gp.buttons[14].pressed) {
                respondToButton = false;
                control.next(1)
                respondToButton = true;
            };

        }
    }
}

window.requestAnimationFrame(scanInput);

第二次尝试

 var animationFrameID;

function scanInput()
{

    var gp = false;

    if (navigator.getGamepads()[0]) {
        gp = navigator.getGamepads()[0];

            if(gp.buttons[14].pressed) {
                cancelAnimationFrame(animationFrameID);
                control.next(1)
                animationFrameID = window.requestAnimationFrame(scanInput);
            };


    }
}

window.requestAnimationFrame(scanInput);

修改 在这一刻,我正在看javascript承诺,但我似乎无法正确掌握这个概念。什么是最简单的承诺形式?我在网络上看到了许多不同的实现。

修改1 尝试使用promises的新方法,但这也没有提供首选行为。

    function scanInput() {

    if (navigator.getGamepads()[0]) {
        var gp = navigator.getGamepads()[0];

            switch(true){

                case gp.buttons[0].pressed:
                    var promise = new Promise(function(resolve, reject){
                        resolve(control.enter());
                    });
                    promise.then(function(result){
                        window.requestAnimationFrame(scanInput);
                    });
                    break;

                case gp.buttons[1].pressed:
                    var promise = new Promise(function(resolve, reject){
                        resolve(control.back());
                    });
                    promise.then(function(result){
                        window.requestAnimationFrame(scanInput);
                    });
                    break;

                case gp.buttons[13].pressed:
                    var promise = new Promise(function(resolve, reject){
                        resolve(control.prev(1));
                    });
                    promise.then(function(result){
                        window.requestAnimationFrame(scanInput);
                    });
                    break;

                case gp.buttons[14].pressed:
                    var promise = new Promise(function(resolve, reject){
                        resolve(control.next(1));
                    });
                    promise.then(function(result){
                        window.requestAnimationFrame(scanInput);
                    });
                    break;
                default:
                    window.requestAnimationFrame(scanInput);
                    break;
            }
    }
};
window.requestAnimationFrame(scanInput);

1 个答案:

答案 0 :(得分:0)

看起来你正在立即解决这些承诺。查看Promise文档,function(resolve, reject)即时运行,因此您可以立即调用resolve()

我不知道control.next等的实现是什么样的,但是他们自己需要返回一个promise(只有在“完成”时才解决),然后你可以这样做:

control.next(1)
.then(function(result){
     window.requestAnimationFrame(scanInput);
})

你也可以使用回调而不是promises,使control函数将函数作为最后一个参数(当它们“完成”时调用),并将它们称为:

control.next(1, function(){
     window.requestAnimationFrame(scanInput);
})

那就是说,听起来你在按下每个按钮时都在做HTTP请求。有更好的方法可以做到这一点:socket.io是一个不错的选择。甚至有一个python server implementation,但我建议使用Node,除非你已经用Python编写了复杂的逻辑。您不必担心发送多个请求,因为它们可能是微小的快速消息。

一些注意事项:

  • 您需要检查navigator.getGamepad本身是否存在以实际检测游戏手柄支持而不会在不支持时出现错误。

  • 您无需为要声明的变量提供值。默认情况下,它会获得值undefined,而undefinednull都是用于“无对象(尚未)”的值,而不是像false这样的布尔值。 (您也可以在var gp =块中执行if; var声明不必位于函数的顶部。)