0

I've seen many others ask questions to do with this but none of the answers actually work and don't apply to my situation.

I just simply want to implement a delay within my for each loop of variable time lengths. These variable time lengths come from the array I am looping through when reading the json file. To give further context, the aim is to highlight each word in a sentence for a variable amount of time - each word has timing in milliseconds associated with it from the json file.

My assumption is that the solution is something to do with setTimeout but every time I try that it waits initially but then skips all the rest.

My code right now:

  $("[id^='timing_check']").click(function() {
    sn = $(this).attr('name');
    ayahnum = $(this).attr('data-id');

    $.getJSON("/static/json/mishary.json", function(result) {
      $.each(result, function(i, v) {
        if (v.ayah == ayahnum && v.surah == sn) {
          var x = v.segments;
          var i = 1;

          x.forEach(function(item) {
            time_sleep = item[3];
            wordref = sn + ':' + ayahnum + ':' + i;
            i++;

            setTimeout(function() {
              $("[name='" + wordref + "']").css('color', 'red');
            }, time_sleep);
          });
        }
      });
    });
  });
});             

This doesn't work at all. Not even close. Please offer some guidance

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
SkyBlue
  • 293
  • 4
  • 13
  • 2
    For us to diagnose any issues we will need to see the HTML as well as an example of the JSON response – Rory McCrossan May 29 '18 at 14:42
  • Also... should all words being colored at once for a random amount of time, or should the next word receive color after the last one lost it - because in the later case a forEach wouldn't be the right choice... also if the text is very long it's possible you don't see anything because your forEach is blocking the thread, as the Jquery-Selection can be very slow... i ran in a similar problem wenn doing validation of a lot of rows... Javascript ( without web-workers) single threaded and setTimeout moves the payload to perform at the last position of the active thread... – Florian May 29 '18 at 14:59
  • So when your running methode doesn't finish you don't get to see anything becouse the timeouts aren't executed... At least as far as i know... Take it with a grain of salt... – Florian May 29 '18 at 15:00
  • here: https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example https://stackoverflow.com/questions/5226285/settimeout-in-for-loop-does-not-print-consecutive-values – admcfajn May 31 '18 at 13:45
  • Possible duplicate of [JavaScript closure inside loops – simple practical example](https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – admcfajn May 31 '18 at 13:46

1 Answers1

1

I think the problem is as follow, let's suppose this code:

array1 = [1000, 2000, 1000, 4000, 10000];
array1.forEach(function(item) { //all actions start at 0

        setTimeout(function() {
            console.log("some action of item "+item);
        }, item);

    }

);

All setTimeout function are calculated from 0+item time, so the times 1000 and 1000 are going to be executed at the same time. Maybe you want to account the time like item[i1]+item[i2], then you have to sum all the times spent in each iteration. The code in that way would be something like:

array1 = [1000, 2000, 1000, 4000, 10000];

var abs = 0;//beginning 

array1.forEach(function(item) {

        if(!abs){
            abs = item;
        }else{
            abs += item;//sum time spent
        }
        console.log("set "+abs+" to setTimeout");

        setTimeout(function() {
            console.log("some action of item "+item);
        }, +abs);

    }

);

In this example, the 2th 1000 will be calculated after 1000 and 2000 that is 4000 ms after the loop is fired.

Emeeus
  • 5,072
  • 2
  • 25
  • 37