Non
Non

Reputation: 8589

How to do a queue in order to wait 5 seconds to execute a function

I need to put a debounce everytime that an object is updated.

Here is the function I need to solve

updatePlayerAmount (data) {
    this.state.playerSlots[data.position - 1].playerAmount = data.playerAmount;
  }

the param data returns something like this

{
  playerAmount : 10,
  position     : 2
}

the playerAmount key will change his value on every click in a certain element.

SO:

everytime the user clicks on certain element, that amount is going to change in the view, but I need that amount to be updated every 5 seconds, it does't matter whether the user clicks 7 times within 2 seconds.

I did it with a setTimeout of 5 seconds, but the issue I had, was that the user clicked on the element 7 times within the 5 seconds, and you couldn't see the changes one by one but the full change only once. And I need the user visualizing the changes in the view every 5 seconds.

According to an explanation a coworker gave me, I need to put the new changes in an array, and be listen to those changes... (?) but, how ?

Did you get it ?

PS: I am using lodash but I don't how to use it in this case.

Update

I did it like this

  _playerAmount = (data) => {
    this.state.playerSlots[data.position - 1].playerAmount = data.playerAmount;
  }

  updatePlayerAmount (data) {
    _.debounce(this._playerAmount(data), 5000);
  }

but I get an error in the console

Uncaught TypeError: Expected a function

so, what are your recommendations here ?

Upvotes: 1

Views: 842

Answers (2)

Danmoreng
Danmoreng

Reputation: 2367

The parts in your question are contraray:

First you say you want to update only every 5 seconds, not when a user clicks.

everytime the user clicks on certain element, that amount is going to change in the view, but I need that amount to be updated every 5 seconds, it does't matter whether the user clicks 7 times within 2 seconds.

Then you say the change is only seen after those 5 seconds if he clicked several times.

I did it with a setTimeout of 5 seconds, but the issue I had, was that the user clicked on the element 7 times within the 5 seconds, and you couldn't see the changes one by one but the full change only once. And I need the user visualizing the changes in the view every 5 seconds.

What exactly do you want? I can help you if you answer me that question.

Edit:

Ok I think I do understand now what you meant by "queueing up the clicks" - this should do it:

function updatePlayerAmount(data) {
    this.state.playerSlots[data.position - 1].playerAmount = data.playerAmount;
}

var clicks = []; // Array to save every new data object in
var notRunning = true; // boolean to determine if there still is a timeout running

function click(data){
    // on each click the data is pushed into the clicks array,
    // then startUpdate() is called
    clicks.push(data);
    startUpdate();
}

function startUpdate(){
    // the worker which makes the timeouts is only called if there
    // is no timeout running still
    if(notRunning){
        notRunning = false;
        worker();       
    }
}

function worker(){
    // if there are no clicks left the worker will stop
    if(clicks.length == 0){
        notRunning = true;
    }else{
        // else it will set a timeout
        window.setTimeOut(function(){
            // updatePlayerAmount is called with the first data in clicks
            updatePlayerAmount(clicks[0]);
            // the first data in clicks gets removed from the array
            clicks.shift();
            // worker calls itself to see if there are still clicks
            worker();
        }, 5000)
    }
}

Upvotes: 0

gen_Eric
gen_Eric

Reputation: 227270

You need to pass .debounce a function. Right now you are calling this._playerAmount(data) and passing its return value (undefined) to .debounce.

Try this:

_.debounce(this._playerAmount.bind(this, data), 5000);

You can also do:

var func = this._playerAmount;
_.debounce(function(){
    func(data);
}, 5000);

Upvotes: 1

Related Questions