2014-09-26 72 views
0

我目前使用AJAXDjango框架。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,并用一个进度条来显示用户的当前进度。

用来获取Django的结果的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可以超过10K,它会冻结网页浏览器,即使它仍在绘图。

我很新的网页设计(不到4个月),但我认为这是因为他们都在同一个线程上运行。

有没有一种方法在JavaScript做线程/异步?我进行了搜索,结果被推迟/承诺,目前看起来非常抽象。

回答

3

尝试逐步处理检索到的数据。

在下面的片段中,以250个块为单位生成元素,主要利用jQuery deferred.notify()deferred.progress()

处理所有10,000个项目时,deferred对象为resolved,其中包含10,000个元素。然后在deferred.then().done()回调中单个呼叫.html()将元素添加到document; .fail()回调投影为null

或者,可以在deferred.progress回调内将元素附加到document的块中;而不是在完成整个任务时发生的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始终是单线程的。

诀窍不是通过JS构建DOM元素。这总是会很昂贵和缓慢。而不是从Django以JSON方式传递数据并动态构建DOM,您应该让Django在服务器端渲染模板片段,然后将整个内容传递给前端,JS可以将其插入相关点。

+0

是否有任何替代品不是这样做呢?因为整个页面都是动态的,这意味着某些表由JS创建,然后使用AJAX填充。在这个过程中没有更新? – user1157751 2014-09-26 22:08:58

+0

但这就是为什么我说要呈现一个片段,而不是整个页面。每个表格仍然可以是单独的Ajax调用,但服务器会返回您插入的HTML块。 – 2014-09-26 22:13:25

+0

@DanielRoseman为什么要麻烦?为什么不使用现有数据并在前端生成模板并添加一次呢?为什么要在客户端和服务器之间混合数据和HTML? – Ian 2014-09-26 22:16:06