2

I'm trying to explain my problem to know the better way to solve it. I've searching a bit, but I don't know how to search exactly:

  • I have an HTML page with three areas: Panel A, Grid B and Grid C.
  • On grid C, I can do an action on a row (only clicking it) that updates some counters on panel A and Grid B, but they're calculated on database totals.
  • When I do the row action I update the row immediately and trigger an event listened by Panel A and Grid B which sends both requests against the server to update it's counters.

Every row update is a bit heavy and if the user clicks various rows fast, the javascript execution is locked flooding the server with updates of Panel A and Grid B which could be deferred to execute only one time if on 1 or 2 seconds the event is not triggered.

I would solve the problem on the listenTo callback because it could be another panel that the event action must be performed "immediately".

I imagine something like this (only refresh after 2 seconds of no event listened), but I think that there must be a better way:

var eventTimeout = {}; // one for listener
element.bind('eventName' function() {
    if (eventTimeout['eventName']) {
        clearTimeout(eventTimeout['eventName']); // I understand that if the timeout has been exhausted no error is thrown
    }
    eventTimeout['eventName'] = 
        setTimeout(function() {
            eventTimeout['eventName'] = null;
            doAction(); 
        }, 2000);
});

I'll go away with that implementation (I haven't tested yet), when I have more time, I'll put it on a JSFiddle to help to understand.

2 Answers 2

1

You are on the right track with your code but you may want to use something like lodash-throttle function decorators rather than reinventing the wheel here IMO.

lodash Throttle

Creates a throttled function that only invokes func at most once per every wait milliseconds. The throttled function comes with a cancel method to cancel delayed invocations. Provide an options object to indicate that func should be invoked on the leading and/or trailing edge of the wait timeout. Subsequent calls to the throttled function return the result of the last func call.

examples from their own site:

// avoid excessively updating the position while scrolling
jQuery(window).on('scroll', _.throttle(updatePosition, 100));

// invoke `renewToken` when the click event is fired, but not more than once every 5 minutes
jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
  'trailing': false
}));

// cancel a trailing throttled call
jQuery(window).on('popstate', throttled.cancel);
Sign up to request clarification or add additional context in comments.

1 Comment

Ohh! It's just what I want! Thanks!
0

Using the previous @bhantol very valuable response, and some other stackoverflow responses (https://stackoverflow.com/a/43638411/803195) I've published a sample code that simulates the behavior I actually want.

Perhaps it was not well defined on initial question, but I need actually use debounce and it must be dynamic, depending on some variables (a checkbox on the following sample) it must be "delayed" or "immediate":

https://codepen.io/mtomas/pen/xYOvBv

var debounced = _.debounce(function() {
  display_info($right_panel);
}, 400);
$("#triggerEvent").click(function() {
  if (!$("#chk-immediate").is(":checked")) {
    debounced();
  } else {
    display_info($right_panel, true);
  }
});

The sample is based on a original sample published on that (interesting) article:

https://css-tricks.com/debouncing-throttling-explained-examples/

-- UPDATE -- Using debounce of lodash implies me to import full lodash (72Kb minimized), so I've implemented a "lite" own debounce using this reference:

https://davidwalsh.name/function-debounce

function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

I've updated my codepen test too.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.