How to create a "load" until the function is fully executed?

Asked

Viewed 134 times

4

Hello. To get to the point: assuming that I have a function with repetition structures that, depending on what the user fills, the existing process in this function can take some time, and while it is not fully completed, the page is locked. Is there any resource I can turn to, so that instead of the page crashing, this load can happen "internally", and while this page works normally?

For example: https://jsfiddle.net/SamirChaves/d2red81z/

In the above situation, there is an automatic creation of a table, from the order (n x m), indicated by the user. But, if the user chooses 100 x 100, for example, the system will create the table, however, it will require a somewhat lengthy load time, and in the meantime the page will remain locked. I need somehow that this does not happen, that in the course of the table creation process, the page continues to work normally and, for example, a gif load appear until full completion.

That is a question that has persisted for some time, but I have found nothing about it, or I have not been able to look for it. In case anyone can help me, I’d like to thank you.

  • Would you happen to have an example where this happens?

  • 1

    I will edit the comment with a practical example.

  • Pegunta edited!

  • 1

    I don’t know much about it, so I won’t make it an answer (someone else can do it!), but probably their solution is the Web Workers. They’re like threads, but with some restrictions. Documentation on MDN (English): https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers

  • I’ll take a look Pablo, thank you.

  • 1

    You can use the server to do this calculation and return HTML?

  • Also I haven’t answered yet because I don’t know much about it (maybe I’ll do a search here), but I also thought the same as @Sergio,.

  • I can suggest for you to use AJAX, you load the table with the processing on a separate page, created just for that. Then take the HTML return or anything else from the answer. That way the page keeps running and you still have the option to put a "Loading" at the time of loading

  • You would have an example of how this would work?

Show 4 more comments

1 answer

3


Come on...

Your code has some bad practices. But I will stick to the main one. Whenever working with js and mass data manipulation avoid doing too many accesses to the DOM. I will quote an example:

document.getElementByQualquerCoisa().innerHTML = 'Algo';

Every time you do that a baby seal dies in the tarta

And why it happens?

Because whenever an access to the DOM is made the browser needs to go through ALL the structure to find the said element it is looking for. This Bush the browser. Ex.:

<div>
    <table>
        <tr>
            <td><input type="text" id="ipTeste"/></td>
        </tr>
    </table>
</div>

In this example to get to ipTeste will be necessary:

Access div -> table -> tr -> td -> input

Does it look like little thing? Yes it really is! But do not forget that in your case you will have a mega structure. In that case the performance will be felt from afar.

Another thing, in case you look for a table then it’s even worse, because in addition to having to go through the DOM you will have a lot of information that you probably won’t need. Other thing, information like style, class and etc are also returned, ie all attributes.

So what to do?

It seems obvious and it is. Avoid access to the DOM in cases such as your search to use a framework that abstracts this type of behavior. I’ll name one I use and get one of the best: https://angularjs.org/

Below is an example of your program using angular:

var app = angular.module('App', []);
app.controller('AppController', function($scope){
    $scope.column = 5;
    $scope.row = 5;
    
    $scope.range = function(count){
        var ratings = []; 
        for (var i = 0; i < count; i++) { 
            ratings.push(1) 
        } 
        return ratings;
    }   
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="App" ng-controller="AppController">
    <form id="create_table" action="javascript:process()">
        <input type="text" id="column" ng-model="column"> x <input type="text" id="row" ng-model="row"> 
        <input type="submit" value="Criar Matriz">
    </form>
   <div>
        <table class="tg">
            <tr ng-repeat="r in range(row) track by $index">
                <td ng-repeat="c in range(column) track by $index">
                    <input type="text" class="cells" style="width: 12px;" value="1"/>
                </td>
            </tr>
        </table>
    </div>
</div>

And with pure js. I used a time out not to crash the browser:

function ps(n) {
  return parseFloat(n);
}

var MTZ = document.getElementsByClassName("tg");
var statusInProcess = false;

function createTable() {
  
  rows = document.getElementById("row");
  columns = document.getElementById("column");

  var N = 0;
  var Column = [];
  var Row = [];

  var table = document.createElement('table');
  table.setAttribute('class', 'tg');

  for (var g = 0; g < columns.value; g++) {
    var fnAsync = function(g) {
      Row.push(table.insertRow(g));
      Row[g].setAttribute('class', 'spine');

      for (var q = 0; q < rows.value; q++) {
        Column[q] = Row[g].insertCell(q);
        Column[q].setAttribute('class', 'line');
        var input = document.createElement("input");
        input.type = "text";
        input.value = 1;
        input.setAttribute('class', 'cells');
        Column[q].appendChild(input);
        input.style.width = (input.value.length * 12) + "px";
        N++;
      };
    };

    setTimeout(fnAsync(g), 1);
  };
  var div = document.getElementById('divTable');
  div.appendChild(table);
}

function setMatriz(number, type) {

  var Mz = MTZ[number];

  var Rows = parseFloat(order(Mz)[0]);
  var Columns = parseFloat(order(Mz)[1]);

  var n = 0;
  var cell = new Array();
  var lines = [];

  for (var j = 0; j < Columns; j++) {

    cell[j] = [];

    for (var i = 0; i < Rows; i++) {

      lines.push(document.getElementsByClassName('cells')[n]);
      cell[j] = lines;
      n++;
    };
    lines = [];
  }
  statusInProcess = false;
}

function process() {
  createTable();
}
<input type="text" id="column">x
<input type="text" id="row">
<input type="button" value="Criar Matriz" onclick="process()">


<div id="divTable">

</div>

  • Great explanation. I will study the use of frameworks in more depth. Thank you for your attention.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.