-2

I have a scenario in my project which I have to have two for loops one after each other :

for (var i = this.props.activeChannel.channelsArr.length - 1; i > -1; i--) {
  $("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase()).find("img").attr("src", "http://localhost:3003/images/menu-icons/" + $("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase()).find("img").attr("src").getTheImgNameFromUrl().replace("-grey", "") + ".png");
  $("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase()).addClass("dummyActive");
  $("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase()).removeAttr("style").css({
    "background-color": "#96A2B3"
  });
  $("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase()).removeClass("dummyNotActive");
  $("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase() + " a");
  $("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase() + " div").removeClass().addClass("channel-activation-btn").removeAttr('style');
  //$("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase()+" a").css({"display":"block"});
  $("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase()).insertBefore("#" + $("#content li:nth-child(1)").attr("id"));
}

for (var i = this.props.activeChannel.channelsArr2.length - 1; i > -1; i--) {
  $("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase()).removeClass("dummyActive").addClass("dummyNotActive");
  $("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase()).removeAttr("style").css({
    "background-color": "#E5E8EC"
  });
  // $("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase()+" div").removeClass("channel-activation-btn");
  // $("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase()+" div").removeClass().removeAttr( 'style' ).css({"width":"100%","height":"100%"});
  //$("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase()).insertBefore("#" + $("#inactiveContainer li:nth-child(1)").attr("id"));
  $("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase()).appendTo("#inactiveContainer");
}

So as you can see there are two for loops and inside each there are couple lines which manipulate css and insert element in different positions and there is no Asynch call(Ajax) in them. what I need to know are the above for loops will execute sequentially? It is very important for me that the first loop finishes with all the lines in it executed and then the second for loop starts execution. So can I say 100% sure that the second loop will execute after the first loop is finished?

Barmar
  • 741,623
  • 53
  • 500
  • 612
Hamed Minaee
  • 2,480
  • 4
  • 35
  • 63
  • Why would think they aren't executed synchronously? – Scott Hunter Mar 15 '17 at 19:16
  • The loops are executed synchronously. But, the page rendering will be done after all the JS has been executed, hence you can't see the changes made to class names in the first loop, when the second loop will reverse the changes. – Teemu Mar 15 '17 at 19:19
  • @ScottHunter I searched about it and I noticed that for loops are synchronous but I just want to make sure my understanding since I have had a lot of issues with asynchronous executions and I need to make sure about – Hamed Minaee Mar 15 '17 at 19:20
  • @Teemu Thanks for answering the lines of code are just an example of what I am trying to do in the loops and will be changed. So can I say that the second loop lines will always execute after the first loop and ? (can you explain more) – Hamed Minaee Mar 15 '17 at 19:22
  • I'm not sure what else to say, maybe check http://stackoverflow.com/q/2734025/ – Teemu Mar 15 '17 at 19:32

3 Answers3

1

Yes. None of the functions called contain any asynchronous aspect to them. All of the effects of the first loop will resolve before the second loop is called.

user5090812
  • 888
  • 1
  • 7
  • 7
1

Almost all JavaScript code is run synchronously, line-by-line.

Unless you use an explicitly asynchronous construct like setTimeout, setInterval, event listeners, Promises or generators, you can rest assured that your for-loops will execute one after the other.

// This runs first
for (var i = 0; i < 10; i++) {
  console.log('First loop: ', i)
}

// This runs second
for (var i = 0; i < 10; i++) {
  console.log('Second loop: ', i)
}
.as-console-wrapper { min-height: 100vh; }
gyre
  • 16,369
  • 3
  • 37
  • 47
1

Javascript has a few asynchronous concepts like:

  • timeouts
  • callbacks
  • event listeners
  • generator functions (ES2015)
  • promises
  • async functions (ES7)

All the "common" elements you know from other languages are processed synchronously.

For completeness sake I refactored your code:

for (var i = this.props.activeChannel.channelsArr.length - 1; i > -1; i--) {

  // define the element once
  let $element = $("#" + this.props.activeChannel.channelsArr[i].channelName.replace(/ /g, '-').toLowerCase());

  // don't do this inline to increase readability
  let newSrc = "http://localhost:3003/images/menu-icons/" + $element.find("img").attr("src").getTheImgNameFromUrl().replace("-grey", "") + ".png";
  
  // and then just work with it, chaining all the calls
  $element.find("img").attr("src", newSrc);
  $element.addClass("dummyActive")
  .removeAttr("style")
  .css({"background-color":"#96A2B3"})
  .removeClass("dummyNotActive");

  // ... and so on

}

I hope you get the gist.

Christoph
  • 50,121
  • 21
  • 99
  • 128