0

I have the following range slider:

<input type="range" min="0" max="511" value="208" step="0.01" oninput="slider_move();perform_calculation()">

The slider_move() function only updates the value shown in an associated input-number field. What I am concerned about is the perform_calculation() function which looks like this (shortened version):

function perform_calculation() {
var isValid = $('#formname').valid();
var value1 = _("value1").value;
var value2 = _("value2").value;
...

if(isValid){
  var formdata = new FormData();
  formdata.append("value1", value1);
  formdata.append("value2", value2);
  ...
  var ajax = new XMLHttpRequest();  
  ajax.addEventListener("load", completeHandler, false);
  ajax.addEventListener("error", errorHandler, false);
  ajax.open("POST", "/calculator.php");   
  ajax.send(formdata);      
 }
}

With event handlers:

function completeHandler(event) {
  _("result").innerHTML = event.target.responseText;
}

function errorHandler(event) {
  _("result").style.color = "red";
  _("result").innerHTML = "Some error msg.";
}

(Note that I have this shorthand function in the page header:

function _(el) {
 return document.getElementById(el);
}

)

So basically, as a user moves the slider, I assume that the AJAX call is executed dozens of times per second (not exactly sure how often an "input" event occurs as the slider is moved). Of course the nice thing about doing it this way is that the user sees the page updated with the calculation results as the slider gets moved (and the input value changed), but I am worried that this is too resource intensive and may cause the server to slow down if there are many users on the page. Should I be worried and if so, is there a better way to do this while maintaining the same functionality?

Pete
  • 105
  • 1
  • 9
  • It's pretty hard to answer this since we have no idea what your PHP code actually does, more than "calculations". However, hammering the server with requests is rarely a good idea. Is there a specific reason you need to do the calculation in PHP instead of in JS directly? – M. Eriksson Aug 13 '22 at 09:11
  • @M.Eriksson: calculator.php contains about 280 lines of code. About half are variable declarations and reading in the $_POST variables from the AJAX call. In terms of calculation there are about 50 lines (some garden variety */+- with some calls to the min and max functions) and then another 50 lines where I assemble the result in a table which I return to the calling page with ´echo $result;´. One reason I am doing it on a separate page in PHP instead of JavaScript is that I do not want to the code that does the calculation to be visible (and thus copyable). – Pete Aug 13 '22 at 09:18

1 Answers1

1

You want to throttle the event probably unless you need all the middle values. A throttle is applying maximum rate of actions. You may compare that to debounce which set a timer interval delay between consecutive actions (not relevant here anyway). Those are not statement of javascript but may libraries implement those. Here's a short example: (there are simpler implementations of throttle)

var perform_calculation_throttled = throttle(perform_calculation, 500);

count = 1
function perform_calculation() {
  console.log("doing ajax #" + count++);
}

function slider_move() {
document.querySelector("input[type=text]").value = document.querySelector("input[type=range]").value
}

// from _.js
function throttle(func, wait, options) {
  wait = wait || 250;
  var timeout, context, args, result;
  var previous = 0;
  if (!options) options = {};

  var later = function() {
    previous = options.leading === false ? 0 : Date.now();
    timeout = null;
    result = func.apply(context, args);
    if (!timeout) context = args = null;
  };

  var throttled = function() {
    var now = Date.now();;
    if (!previous && options.leading === false) previous = now;
    var remaining = wait - (now - previous);
    context = this;
    args = arguments;
    if (remaining <= 0 || remaining > wait) {
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      previous = now;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    } else if (!timeout && options.trailing !== false) {
      timeout = setTimeout(later, remaining);
    }
    return result;
  };

  throttled.cancel = function() {
    clearTimeout(timeout);
    previous = 0;
    timeout = context = args = null;
  };

  return throttled;
}
<input type="range" min="0" max="511" value="208" step="0.01" oninput="slider_move();perform_calculation_throttled()"><input type="text" readonly>
IT goldman
  • 14,885
  • 2
  • 14
  • 28