2014-09-26 5 views
0

Я в настоящее время использую AJAX с Django Рамки.jQuery - Могут ли потоки/асинхронные операции?

Я могу пройти asynchronous POST/GET до Django, и пусть он вернет объект json.

Затем, в соответствии с результатом, полученным от Django, я прокручу данные и обновляю таблицу на веб-странице.

HTML, для таблицы:

<!-- Modal for Variable Search--> 
<div class="modal fade" id="variableSearch" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> 
    <div class="modal-dialog"> 
     <div class="modal-content"> 
      <div class="modal-header"> 
       <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button> 
       <h4 class="modal-title" id="myModalLabel">Variable Name Search</h4> 
      </div> 
     <div class="modal-body"> 
      <table id="variableSearchTable" class="display" cellspacing="0" width="100%"> 
       <thead> 
        <tr> 
         <th> Variable Name </th> 
        </tr> 
       </thead> 
      </table> 
      <p> 
       <div class="progress"> 
        <div class="progress-bar progress-bar-striped active" id="variableSearchProgressBar" role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 45%"> 
         <span class="sr-only">0% Complete</span> 
        </div> 
       </div> 
      </p> 
      <p> 
       <div class="row"> 
        <div class="col-lg-10"> 
         <button class="btn btn-default" type="button" id="addSearchVariable" >Add</button> 
        </div> 
       </div> 
      </p> 
     </div> 
      <div class="modal-footer"> 
       <button type="button" class="btn btn-default" id="variableSearchDataCloseButton" data-dismiss="modal">Close</button> 
      </div> 
     </div> 
    </div> 
</div> 

В основном это bootstrap 3 модальный, с jQuery DataTable, и с помощью индикатора, чтобы показать пользователю текущий прогресс.

The Javascript, который используется для получения результатов Джанго:

$('#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(
        $(
         '<tr>' + 
          '<td>' + response.variables[i] + '</td>' + 
         '<tr>' 
        )[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"); 
}); 

Проблема заключается с обновлением таблицы части:

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

Поскольку response.variables может быть более 10 кОм, и он будет заморозить веб-браузер, хотя он все еще рисуется.

Я довольно новичок в веб-дизайне (менее 4 месяцев), но я предполагаю, что это потому, что все они работают по одной теме.

Есть ли способ в Javascript для потоковой обработки/async? У меня был обыск, и результаты были отложены/обещаны, которые на данный момент очень абстрактны.

ответ

3

Попробуйте обработать полученные данные пошагово.

На рисунке ниже элементы, генерируемые в блоках 250, в основном с использованием jQuery deferred.notify() и deferred.progress().

Когда все 10 000 предметов обработано, объект deferred является resolved с коллекцией из 10 000 элементов. Затем элементы добавляются к document при одном вызове .html() в пределах .done() callback; .fail() callback литой как null.

В качестве альтернативы, можно добавить элементы к document в блоках 250, в пределах deferred.progress callback; вместо одного вызова в пределах deferred.done, который возникает по завершении всей задачи.

setTimeout предназначен для предотвращения "замораживания веб-браузера".

$(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('<tr>' + 
 
       '<td>' + arr[i] + '</td>' + 
 
      '</tr>') 
 
     //)[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]); 
 
    } 
 
}) 
 
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 
<progress min="0" max="10000"></progress><output for="progress"></output> 
 
<output for="progress"></output><br /> 
 
<table id="results"></table>
jsfiddle http://jsfiddle.net/guest271314/ess28zLh/

1

Отсрочки/обещания вам не помогут. JS в браузере всегда однопоточен.

Трюк заключается не в создании элементов DOM через JS. Это всегда будет дорого и медленно. Вместо того, чтобы передавать данные в JSON из Django и динамически создавать DOM, вы должны заставить Django отобразить фрагмент шаблона на стороне сервера и передать все это на передний план, где JS может просто вставить его в соответствующую точку ,

+0

Существуют ли какие-либо альтернативы, чем делать это? Поскольку вся страница является динамической, то есть некоторые таблицы создаются JS, а затем заполняются с использованием AJAX. В этом процессе нет обновления? – user1157751

+0

Но вот почему я сказал сделать фрагмент, а не всю страницу. Каждая таблица все еще может быть отдельным вызовом Ajax, но сервер возвращает блок HTML, который вы вставляете. –

+0

@ DanielRoseman Зачем беспокоиться? Почему бы просто не использовать существующие данные и создать шаблон на интерфейсе и добавить его один раз? Зачем смешивать данные и HTML между клиентом и сервером? – Ian