jQuery - 可以完成线程/异步吗? [英] jQuery - Can threads/asynchronous be done?

查看:34
本文介绍了jQuery - 可以完成线程/异步吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用 AJAXDjango 框架.

我可以将 asynchronous POST/GET 传递给 Django,并让它返回一个 json 对象.

然后根据Django传过来的结果,循环遍历数据,更新网页上的表格.

表格的 HTML:

<div class="modalfade" 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">关闭</span></button><h4 class="modal-title" id="myModalLabel">变量名搜索</h4>

<div class="modal-body"><table id="variableSearchTable" class="display" cellpacing="0" width="100%"><头><tr><th>变量名</th></tr></thead><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="宽度:45%"><span class="sr-only">0% 完成</span>

</p><p><div class="row"><div class="col-lg-10"><button class="btn btn-default" type="button" id="addSearchVariable" >添加</button>

</p>

<div class="modal-footer"><button type="button" class="btn btn-default" id="variableSearchDataCloseButton" data-dismiss="modal">关闭</button>

基本上它是一个 bootstrap 3 模式,带有 jQuery DataTable,并带有一个向用户显示当前进度的进度条.

用于获取 Django 结果的 Javascript:

$('#chartSearchVariable').click(function(event){$('#chartConfigModal').modal("隐藏");$('#variableSearch').modal("show");var csrftoken = getCookie('csrftoken');var blockname = document.getElementById('chartConfigModalBlockname').value;$('#variableSearchProgressBar').css('width', "0%").attr('aria-valuenow', "0%");event.preventDefault();$.ajax({类型:获取",url:"ajax_retreiveVariableNames/",超时:4000000,数据:{'csrfmiddlewaretoken':csrftoken,'块名':块名},成功:功能(响应){如果(响应.状态==无效"){$('#chartConfigModal').modal("隐藏");$('#variableSearch').modal("隐藏");$('#invalid').modal("show");}别的{configurationVariableChart.row('').remove().draw(false);for (i = 0 ; i < response.variables.length; i++){configurationVariableChart.row.add($(''+'<td>'+ response.variables[i] + '</td>'+'')[0]);}configurationVariableChart.draw();$('#variableSearchProgressBar').css('width', "100%").attr('aria-valuenow', "100%");}},失败:功能(响应){$('#chartConfigModal').modal("隐藏");$('#variableSearch').modal("隐藏");$('#invalid').modal("show");}});返回假;});$('#addSearchVariable').click(function(event){$('#variableSearch').modal("隐藏");$('#chartConfigModal').modal("show");document.getElementById('chartConfigModalVariable').value = currentVariableNameSelects;});$('#variableSearchDataCloseButton').click(function(event){$('#variableSearch').modal("隐藏");$('#chartConfigModal').modal("show");});

问题在于更新表部分:

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

因为 response.variables 可能超过 10k,它会冻结 Web 浏览器,即使它仍在绘制.

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

Javascript 中有没有办法进行线程/异步?我进行了搜索,结果被推迟/承诺,目前看起来很抽象.

解决方案

尝试以增量方式处理检索到的数据.

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

当所有 10,000 个项目都被处理时,deferred 对象被 resolved 与 10,000 个元素的集合一起处理.然后在 .html() 的单次调用将元素添加到 documentrel="nofollow">deferred.then().done() 回调;.fail() 回调转换为 null .

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

setTimeout 用于防止冻结网络浏览器"情况.

$(function() {//10k 项var arr = $.map(new Array(10000), function(v, k) {返回 v === 未定义?k : 空});var len = arr.length;var dfd = new $.Deferred();//以 250 块为单位在 `for` 循环中处理的项目集合var 片段 = [];var重绘=函数(){对于 (i = 0 ; i <250; i++){//configurationVariableChart.row.add(//$(fragment.push('' +'<td>'+ arr[i] + '</td>'+'</tr>')//)[0]);};arr.splice(0, 250);控制台日志(片段,arr,arr.length);返回 dfd.notify([arr, fragment])};$.when(重绘())//`done` 回调.then(函数(数据){$("#results").html(data.join(","));删除片段;}//`fail` 回调, 空值//`progress` 回调,功能(数据){//log ,显示任务的进度"控制台日志(数据);$("progress").val(data[1].length);$("output:first").text(Math.floor(data[1].length/100) + "%");$("output:last").text(data[1].length +" of "+ len + " items processing");$("#results").html("正在处理数据...");如果(数据[0].长度){var s = setTimeout(function() {重绘()}, 100)} 别的 {clearTimeout(s);dfd.resolve(数据[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/

I'm currently using AJAX with Django Framework.

I can pass asynchronous POST/GET to Django, and let it return a json object.

Then according to the result passed from Django, I will loop through the data, and update a table on the webpage.

The HTML for the table:

<!-- 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>

Basically it is a bootstrap 3 modal, with jQuery DataTable, and with a progress bar to show the user the current progress.

The Javascript that is used to get Django results:

$('#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");
});

The problem is with the updating table part:

    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%");

Since the response.variables can be over 10k, and it will freeze the web browser, even though it is still drawing.

I'm pretty new to Web Design (less than 4 months), but I assume it's because they are all running on the same thread.

Is there a way in Javascript to do threading/async? I had a search, and the results were deferred/promise which seems very abstract at the moment.

解决方案

Try processing retrieved data incrementally.

At piece below , elements generated in blocks of 250 , primarily utilizing jQuery deferred.notify() and deferred.progress().

When all 10,000 items processed , the deferred object is resolved with the collection of 10,000 elements. The elements are then added to document at single call to .html() within deferred.then()'s .done() callback ; .fail() callback cast as null .

Alternatively , could append elements to the document in blocks of 250 , within deferred.progress callback ; instead of at the single call within deferred.done , which occurs upon completion of the entire task.

setTimeout is utilized to prevent "freeze the web browser" condition .

$(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/

这篇关于jQuery - 可以完成线程/异步吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆