jQuery-可以执行线程/异步操作吗

jQuery - Can threads/asynchronous be done?

本文关键字:异步操作 线程 执行 jQuery-      更新时间:2023-09-26

我目前正在使用AJAXDjango框架。

我可以将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,它将冻结web浏览器,即使它仍在绘图。

我对Web设计还很陌生(不到4个月),但我想这是因为它们都在同一个线程上运行。

Javascript中有没有实现线程/异步的方法?我搜索了一下,结果被推迟了/答应了,这在目前看来非常抽象。

尝试增量处理检索到的数据。

在下面的文章中,元素以250为块生成,主要使用jQuery deferred.notify()和deferred.progress().

当处理完所有10000个项目时,deferred对象是具有10000个元素集合的resolved。然后,在deferred.then()的.done()回调中,在对.html()的单个调用中将元素添加到document.fail()回调强制转换为null

或者,可以在deferred.progress回调内的块250中将元素附加到document;而不是在完成整个任务时发生的deferred.done内的单个调用。

setTimeout用于防止"冻结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('<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>
jsfiddlehttp://jsfiddle.net/guest271314/ess28zLh/

延期/承诺在这里对您没有帮助。浏览器中的JS总是单线程的。

诀窍是不要通过JS构建DOM元素。这总是昂贵而缓慢的。与其从Django中以JSON形式传递数据并动态构建DOM,不如让Django在服务器端呈现一个模板片段,并将整个过程传递到前端,在那里JS可以简单地将其插入相关点。