1

I'm very new in js, I'm working on project for wingsuit pilots (track analyzer).

On page I implement range selector and few charts, so user can select which part of data he want to analyze.

Problem is - sometime user change range from both frontiers, so in that case he waits when finish first calculation and second.

Question is - is there any way to stop execution block of code if user iterate with range slider? I'll be very appreciate for directions to approach this task.

you can visit this page and try it for better understanding - try to change range twice without wait for charts and data update.

EDIT: When user finish with range slider it calls callback function, where I implemented calculations and charts update. Range selector also has onChange callback. So is there any way to stop execution one function from another one? Or may be I should call same function with parameter and do something?

Range slider initializing:

  $(document).ready(function() {

    $("#range_selector").ionRangeSlider({
      min: max_height,
      max: 0,
      type: 'double',
      step: 50,
      prettify: false,
      hasGrid: true,
      from: max_height,
      to: 0,
      onFinish: function (obj) {      // callback is called on slider action is finished
        range_from = obj.fromNumber;
        range_to = obj.toNumber;
        set_chart_data();
      }
    });

Here is computing loop:

    for (var index in charts_data) {

      var current_point = charts_data[index];
      var point = {};

      isLast = true;

      if (current_point.elevation <= max_val && current_point.elevation >= min_val) {

        point = clone(current_point);

        // Корректировка выбранного диапазона
        if (isFirst) {

          isFirst = false;
          if (current_point.elevation != max_val && charts_data.hasOwnProperty(index-1)) {

            point.elevation_diff = max_val - current_point.elevation;

            var k = point.elevation_diff / current_point.elevation_diff;

            point.distance = Math.round(current_point.distance * k);
            point.fl_time = Math.round(current_point.fl_time * k);
          }
        }

        isLast = false;

        dist += point.distance;
        elev += point.elevation_diff;

        elev_data.push([fl_time, Math.round(elev)]);
        dist_data.push([fl_time, dist]);

        heights_data.push([fl_time, Math.round(point.elevation)]);
        h_speed.push([fl_time, point.h_speed]);
        v_speed.push([fl_time, point.v_speed]);

        gr.push([fl_time, point.glrat]);

        fl_time += point.fl_time;

        min_h_speed = min_h_speed == 0 || min_h_speed > point.h_speed ? point.h_speed : min_h_speed;
        max_h_speed = max_h_speed == 0 || max_h_speed < point.h_speed ? point.h_speed : max_h_speed;

        min_v_speed = min_v_speed == 0 || min_v_speed > point.v_speed ? point.v_speed : min_v_speed;
        max_v_speed = max_v_speed == 0 || max_v_speed < point.v_speed ? point.v_speed : max_v_speed;

        min_gr = min_gr == 0 || min_gr > point.glrat ? point.glrat : min_gr;
        max_gr = max_gr == 0 || max_gr < point.glrat ? point.glrat : max_gr;
      }

      if (isLast && elev_data.length > 0) {
        if (current_point.elevation <= min_val && charts_data.hasOwnProperty(index - 1)) {

          point = clone(current_point);
          prev_point = charts_data[index - 1];

          point.elevation_diff = prev_point.elevation - min_val;
          var k = point.elevation_diff / current_point.elevation_diff;

          point.fl_time = current_point.fl_time * k;
          point.elevation = min_val;
          point.distance = Math.round(current_point.distance * k);

          dist += point.distance;
          elev += point.elevation_diff;

          elev_data.push([fl_time, Math.round(elev)]);
          dist_data.push([fl_time, dist]);

          heights_data.push([fl_time, Math.round(point.elevation)]);
          h_speed.push([fl_time, point.h_speed]);
          v_speed.push([fl_time, point.v_speed]);

          gr.push([fl_time, point.glrat]);
        }
        break;
      }
    }
3
  • 1
    You might want to check this : stackoverflow.com/questions/672732/… Commented Jul 11, 2014 at 12:59
  • @naota: That question is about 5 years old... JS has changed quite a bit since then. Not in the least, the addition of the Worker API, which is a much, much better fit for problems like these Commented Jul 11, 2014 at 13:01
  • @EliasVanOotegem, I quite agree with you. Your answer is excellent. I just put the link to show there is an old history and wisdom for this problem. I should have written so. And I guess some developper have to deal with old browsers or mobile browsers which don't support the workers. caniuse.com/webworkers Commented Jul 11, 2014 at 13:11

1 Answer 1

3

Note:
I haven't looked at your link, simply because I'm being cautious. You probably should set up a fiddle, and you certainly should add a minimal code sample to your question. A link alone is not enough.

The short answer is no.

JavaScript is single threaded. It runs in one thread in the browser, and so any code that responds to any action (taken by the user or a piece of code) can't run until the engine has finished doing whatever it is doing at any given time.
When a function is called, the only things that can stop that function from running are: syntax errors, the browser (script is taking too long, browser can kill it), or the function returns (finishes normally). No function can be called when one function is working. Concurrency is impossible. Whatever event listeners you have, the callbacks will be queued, only to be invoked once the function has returned.

There is some good news, though. If the computation really takes, like you say 1 second, then you can create a worker. You can fork off the heavy work to this worker, and add an event listener to the instance, that listends for messages. Write the worker so that, when it is done, it sends a message back to the man JS thread. While the worker is running, the main JS thread can carry on freely.

To stop a worker while it's busy performing some complex computations, you simply invoke the terminate method:

(function()
{
    var w = new Worker('worker/code/script.js'),
        handler = function()
        {
            w.terminate();
        },
        btn = document.querySelector('#stopBtn');
    btn.addEventListener('click', handler, false);
    w.onmessage = function(e)
    {
        btn.removeEventListener('click', handler, false);//listener not needed anymore
        console.log('Worker finished, its response was: ', e.data);
        this.terminate();//kill worker
    };
    //init worker
    w.postMessage('Data to pass to worker here');
}());
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks so much! It is what I was looking for. I didn't set fiddle because of my question is abstract and about directions not about code something. I paste link only with one reason - if I said something incorrect (because of my English) - web page shows it more clear.
I've added code samples. Not sure it makes my question more clear, but better than nothing

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.