jQuery – ¿Se pueden hacer hilos / asíncronos?

Actualmente estoy usando AJAX con Django Framework.

Puedo pasar POST / GET asynchronous a Django y dejar que devuelva un objeto json .

Luego, de acuerdo con el resultado aprobado por Django , revisaré los datos y actualizaré una tabla en la página web.

El HTML para la tabla:

   

Básicamente es un modo bootstrap 3 , con jQuery DataTable , y con una barra de progreso para mostrar al usuario el progreso actual.

El Javascript que se usa para obtener los resultados de Django:

 $('#chartSearchVariable').click(function(event) { $('#chartConfigModal').modal("hide"); $('#variableSearch').modal("show"); var csrftoken = getCookie('csrftoken'); var blockname = document.getElementById('chartConfigModalBlockname').value; $('#variableSearchProgressBar').css('width', "0%").attr('aria-valuenow', "0%"); event.preventDefault(); $.ajax( { type:"GET", url:"ajax_retreiveVariableNames/", timeout: 4000000, data: { 'csrfmiddlewaretoken':csrftoken, 'blockname':blockname }, success: function(response) { if(response.status == "invalid") { $('#chartConfigModal').modal("hide"); $('#variableSearch').modal("hide"); $('#invalid').modal("show"); } else { configurationVariableChart.row('').remove().draw(false); for (i = 0 ; i < response.variables.length; i++) { configurationVariableChart.row.add( $( '' + '' + response.variables[i] + '' + '' )[0]); } configurationVariableChart.draw(); $('#variableSearchProgressBar').css('width', "100%").attr('aria-valuenow', "100%"); } }, failure: function(response) { $('#chartConfigModal').modal("hide"); $('#variableSearch').modal("hide"); $('#invalid').modal("show"); } }); return false; }); $('#addSearchVariable').click(function(event) { $('#variableSearch').modal("hide"); $('#chartConfigModal').modal("show"); document.getElementById('chartConfigModalVariable').value = currentVariableNameSelects; }); $('#variableSearchDataCloseButton').click(function(event) { $('#variableSearch').modal("hide"); $('#chartConfigModal').modal("show"); }); 

El problema es con la parte de la tabla de actualización:

  configurationVariableChart.row('').remove().draw(false); for (i = 0 ; i < response.variables.length; i++) { configurationVariableChart.row.add( $( '' + '' + response.variables[i] + '' + '' )[0]); } configurationVariableChart.draw(); $('#variableSearchProgressBar').css('width', "100%").attr('aria-valuenow', "100%"); 

Dado que response.variables puede tener más de 10k, y congelará el navegador web, aunque todavía esté dibujando.

Soy bastante nuevo en Diseño Web (menos de 4 meses), pero supongo que es porque todos se ejecutan en el mismo hilo.

¿Hay alguna forma en Javascript para hacer threading / async? Hice una búsqueda y los resultados fueron diferidos / promisorios, lo que parece muy abstracto en este momento.

Trate de procesar los datos recuperados de forma incremental.

A continuación, elementos generados en bloques de 250, que utilizan principalmente jQuery deferred.notify () y deferred.progress () .

Cuando se procesan todos los 10 000 elementos, el objeto deferred se resolved con la colección de 10 000 elementos. Los elementos se agregan luego al document en una sola llamada a .html() dentro de la callback .done() ; .fail() callback emitida como null .

Alternativamente, podría agregar elementos al document en bloques de 250, dentro de la callback deferred.progress ; en lugar de en la única llamada dentro de deferred.done , que ocurre una vez completada la tarea completa.

setTimeout se utiliza para evitar la condición de “congelación del navegador web”.

 $(function() { // 10k items var arr = $.map(new Array(10000), function(v, k) { return v === undefined ? k : null }); var len = arr.length; var dfd = new $.Deferred(); // collection of items processed at `for` loop in blocks of 250 var fragment = []; var redraw = function() { for (i = 0 ; i < 250; i++) { // configurationVariableChart.row.add( // $( fragment.push('' + '' + arr[i] + '' + '') // )[0]); }; arr.splice(0, 250); console.log(fragment, arr, arr.length); return dfd.notify([arr, fragment]) }; $.when(redraw()) // `done` callbacks .then(function(data) { $("#results").html(data.join(",")); delete fragment; } // `fail` callbacks , null // `progress` callbacks , function(data) { // log , display `progress` of tasks console.log(data); $("progress").val(data[1].length); $("output:first").text(Math.floor(data[1].length / 100) + "%"); $("output:last").text(data[1].length +" of "+ len + " items processed"); $("#results").html("processing data..."); if (data[0].length) { var s = setTimeout(function() { redraw() }, 100) } else { clearTimeout(s); dfd.resolve(data[1]); } }) }) 
   

Las diferidas / promesas no te ayudarán aquí. JS en el navegador siempre es de un solo hilo.

El truco no es construir elementos DOM a través de JS. Eso siempre va a ser costoso y lento. En lugar de pasar datos en JSON desde Django y construir un DOM dinámicamente, debería hacer que Django renderice un fragmento de plantilla en el servidor y pase todo eso al front-end, donde el JS simplemente puede insertarlo en el punto relevante .