Search code examples
javascriptperformancegoogle-chromeinternet-explorer

Javascript loop way faster in IE than Chrome browsers


I have a simple for-loop in a JS file on an old aspx web page:

function SaveCurrentFilterDisplay() {
    var currentFilterCode = document.getElementById('curfilt').value;
    var currentFilterList, currentFilterDisplay;
    var i, str;

    if (currentFilterCode != '') {
        currentFilterList = document.getElementById(currentFilterCode);
        currentFilterDisplay = document.getElementById(currentFilterCode + '_display');

        //save the previous filter text names
        //alert(currentFilterCode + ': ' + currentFilterList.length);
        if (currentFilterList.length) {
            //multi-select list
            str = '';
            for (i = 0; i < currentFilterList.length; i++) {
                if (currentFilterList.options[i].selected) {
                    if (str.length > 0) {
                        str = str + ', '
                    }
                    str = str + currentFilterList.options[i].text;
                }
            }
        } else {
            //text field
            str = currentFilterList.value;
        }

        alert('finished looping');
        currentFilterDisplay.value = str;
    }

    return true;
}

Sometimes this loop has to loop almost 50,000 times. Others just a few hundred or less.

What is perplexing me is that when the loop has to loop 50,000 times and I run this in Chrome, it takes around 2 minutes. But when I do the exact same thing in IE it takes just a few seconds, sometimes it even seems instantaneous.

I am wondering if there is an explanation having to do with how the Chrome based browsers handle Javascript?

EDIT: And perhaps any suggestions on how to optimize this so that it doesn't take 2 minutes in Chrome?

EDIT 2: I have updated my question to show the entire function. When I step through the function using the Chrome dev tools, all of the statements in the method execute instantly, but when I step over the loop it takes 2 minutes to hit the alert statement, so it is the loop that is taking 2 minutes.

Here is some HTML showing what currentFilterList is getting pointed to:

<select id="ID" name="adv" multiple="true">
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
</select>

So as an example, currentFilterCode = "ID". This makes currentFilterList set to the select list above (Much shorter than the real one for obvious reasons).

Final Edit: After help from comments I did post my solution to the particular problem I was facing. It is not the best way to go about a similar situation, but it works within the constraints of the application I was working on. I chose the other answer as the solution because it is the way to go for similar situations.


Solution

  • So why are we looping to find the selections when we can do it with a selector? Use map and join to build up a string of the selected values.

    document.querySelector("#select1").addEventListener("change", () => {
      const out = [...document.querySelectorAll('#select1 option:checked')].map(x => x.text);
      console.log(out.join(', '));
    });
    
    
    
    /*
    document.querySelector("#select1").addEventListener("change", function() {
      var out = Array.from(document.querySelectorAll('#select1 option:checked')).map(function(x) { return x.text; });
      console.log(out.join(', '));
    });
    */
    <select id="select1" multiple>
      <option>FOO1</option>
      <option>FOO2</option>
      <option>FOO3</option>
      <option>FOO4</option>
      <option>FOO5</option>
      <option>FOO6</option>
      <option>FOO7</option>
      <option>FOO8</option>
      <option>FOO9</option>
      <option>FOO10</option>
    </select>

    OR with selected Options and map and join

    document.querySelector("#select1").addEventListener("change", () => {
      var out = [...document.querySelector('#select1').selectedOptions].map(x => x.text);
      console.log(out.join(', '));
    });
    <select id="select1" multiple>
      <option>FOO1</option>
      <option>FOO2</option>
      <option>FOO3</option>
      <option>FOO4</option>
      <option>FOO5</option>
      <option>FOO6</option>
      <option>FOO7</option>
      <option>FOO8</option>
      <option>FOO9</option>
      <option>FOO10</option>
    </select>