0

Background information: I am trying to make an application with ElectronJS. The backend is a python webserver which starts at the same time electron starts.

I will refer to the python webserver as "the backend" and ElectronJS as "the frontend".

Problem: The animation frame needs to execute a callback to the python webserver which executes a system process. At this time the gamepad button is registered multiple times and executes the request to the backend many times.

Desired behavior: What i want is the requestanimationframe not to respond to consecutive keypresses from the gamepad until the function has finished.

What i have tried: Below i have two of the code samples i have tried. There are many more which i have tried, but do not remember. Does anyone have a solution to my problem as described, or a way to get the desired behavior?

Code samples of my attempts

 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);

Second try

 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);

Edit At this moment i am looking at javascript promises, but i cannot seem to grasp the concept properly. What is the simplest form of a promise? I see many different implementations around the web.

Edit 1 Tried a new way with promises, but this also does not provide the preferred behavior.

    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);
Dany
  • 735
  • 1
  • 8
  • 27
  • At this moment i am reading about JS promises. It seems promising ;) and might be the solution. – Dany Jun 14 '16 at 13:02

1 Answers1

0

Looks like you're resolving the promises instantly. Looking at the Promise docs, the function(resolve, reject) is run instantly, and so you're thereby calling resolve() instantly.

I don't know what the implementations of control.next etc. look like, but they themselves would need to return a promise (that's resolved only when it's "done"), and then you could do:

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

You could also use callbacks instead of promises by making the control functions take a function as the last argument (called when they're "done"), and calling them like:

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

That said, it sounds like you're doing HTTP requests on every button press. There are better ways to do this: socket.io is a nice option. There's even a python server implementation, but I'd recommend using Node unless you have complicated logic already written in Python. You shouldn't need to worry so much about sending multiple requests, because they can be tiny fast messages instead.

Some notes:

  • You need to check if navigator.getGamepad itself exists to actually detect gamepad support without getting an error when there isn't support.

  • You don't need to provide a value to a variable you're declaring. By default it'll get the value undefined, and undefined or null are both better values to use for "no object (yet)" than a Boolean like false. (You can also just do var gp = within the if block; var declarations don't have to be at the top of a function.)

1j01
  • 3,714
  • 2
  • 29
  • 30