在JavaScript for double循环中更新HTML进度条?

时间:2018-04-19 18:55:49

标签: javascript html ajax

我有一个Html输入文件,可以上传图像,并且带有ajax到asp.net MVC控制器,一切正常。

但是我在更新简单的进度条时遇到了麻烦。

这是简单的Html,

<input type="file" multiple="multiple" id="file_upload" />
<br />
<input type="button" id="upload" name="upload" value="Upload" class="btn btn-primary btn-block" />
<br />
<div class="outter">
    <div class="inner" id="progress"></div>
</div>
<br />

在我的javascript中,我正在拆分请求,一次上传10张图片,这是它的外观,

<script>
var counter = 0;

$("#upload").click(function () {
    var fileUpload = $("#file_upload").get(0);
    var files = fileUpload.files;
    var devide = devider(files.length);

    for (var x = 0; x < devide; x++) {
        var fileData = new FormData();
        for (var i = 0; i < files.length / devide; i++) {
            if (counter < files.length) {
                fileData.append(files[counter].name, files[counter]);
                counter++;                  
            }
        }

        $.ajax({
            type: "POST",
            url: "/Upload/GetFiles",
            data: fileData,
            cache: false,
            contentType: false,
            processData: false,
            async: false,
            success: function (result) {
                console.log(result);
            },
            error: function (xhr, status, error) { console.log('Error:' + error); },
            timeout: 0
        });
    }
});

function devider(number) {
    var count = 0;
    for (var i = 0; i < number; i+=10) {
        count++;
    }
    return count;
}
</script>

我只需要在每次上传文件时更新<div id="progress">的宽度,这可能意味着在第二个for循环中。 但我不能,因为它是在一个循环中它没有更新HTML?

P.S。我知道setInterval但我不知道在这种情况下如何实现它??

2 个答案:

答案 0 :(得分:1)

这个问题的答案可能是,您无法更新JavaScript循环中的任何HTML!

我不知道为什么它没有被覆盖更多,但我尝试了我在Chrome和Fiddle中尝试过的所有内容,页面上的HTML将无法更新,直到循环结束执行它无关紧要你尝试从循环本身,或者你调用外部函数,再次 HTML将不会重绘,直到循环执行完毕。

然后我发现this post解释了一点

这是一个引用,

  

JavaScript执行和页面呈现在同一执行中完成   线程,这意味着当你的代码执行时,浏览器会   不要重绘页面。 (即使它正在重绘页面   对于for循环的每次迭代,它都会如此之快   我没有时间看到个别数字。)

所以我不得不放弃for循环以更新HTML,这就是我的JavaScript现在的样子。

<script>

    var counter = 0;
    var index = 0;
    var fileUpload;
    var files;
    var devide;
    var add_width;
    var update_width = 0;
    var fileData;
    var interval;

    document.getElementById("file_upload").onchange = function () {
        fileUpload = $("#file_upload").get(0);
        files = fileUpload.files;
        devide = devider(files.length);
        add_width = 100 / devide;
        $("#progress").css({ "width": "0%", "max-width": "100%" });
    }

    $("#upload").click(function () {
        if (fileUpload) {
            $("#outter").css({ "display": "inline-block" });
            prepareUpload();
        }        
    })

    function prepareUpload() {

        fileData = new FormData();
        for (var i = 0; i < 10; i++) {
            if (counter < files.length) {
                fileData.append(files[counter].name, files[counter]);
                counter++;
            }      
        }
        update_width += add_width;
        document.getElementById("progress").style.width = update_width + "%";
        document.getElementById("text").innerHTML = Math.round(update_width) + " % Completed";
        interval = setInterval(upload, 90);  
    }

    function upload() {
        if (index < devide) {
            $.ajax({
                type: "POST",
                url: "/Upload/GetFiles",
                data: fileData,
                cache: false,
                contentType: false,
                processData: false,
                async: false,
                complete: function () {
                },
                success: function (result) {
                    if (result < files.length) {
                        prepareUpload();
                    } else {
                        clearInterval(interval);
                    }
                },
                error: function (xhr, status, error) { console.log('Error:' + error); },
                timeout: 0
            });
        } else {
            clearInterval(interval);
        }
        index++;       
    }

    function devider(number) {
        var count = 0;
        for (var i = 0; i < number; i += 10) {
            count++;
        }
        return count;
    }

</script>

答案 1 :(得分:0)

我会使用already nicely made progressbar。但这是对你的问题的答案

修改:为您添加了JSFiddle,其中包含一个虚拟进度条:https://jsfiddle.net/strauman/wy7w015e/

您说您希望在文件上传成功后更新进度条。因此,让我们创建一个函数prepare_progressbar来准备步骤数和一个函数update_progressbar来更新它。

首先,我们创建变量以包含我们在两个函数中都需要的值:

var width_per_file;
var number_of_files_completed;
var number_of_files_to_upload=0;

现在我们准备&#34;它通过检查上传了多少文件,并初始化变量。

function prepare_progressbar(number_of_files){
  var max_progressbar_width=$(window).width();
  // Reset the completed-counter
  number_of_files_completed=0;
  // How much should it increase per file completed?
  width_per_file=$(window).width()/number_of_files;
  // Set the global number of files
  number_of_files_to_upload=number_of_files;
  // Make progress bar "hidden"
  $("#progress").css({"max-width": "0px"});
}

现在,我们想要创建一个更新进度条的函数。每次ajax完成请求时,我们都希望它调用此函数:

function update_progressbar(){
  number_of_files_completed+=1;
  var new_progressbar_width=number_of_files_completed*width_per_file;
  $("#progress").css({"width":new_progressbar_width+"px", "max-width":new_progressbar_width+"px"});
}

现在唯一剩下的就是将这些函数插入代码中的适当位置。这一切都像这样:

var width_per_file;
var number_of_files_completed;
var number_of_files_to_upload=0;

function prepare_progressbar(number_of_files){
  var max_progressbar_width=$(window).width();
  // Reset the completed-counter
  number_of_files_completed=0;
  // How much should it increase per file completed?
  width_per_file=$(window).width()/number_of_files;
  // Set the global number of files
  number_of_files_to_upload=number_of_files;
  // Make progress bar "hidden"
  $("#progress").css({"max-width": "0px"});
}

function update_progressbar(){
  number_of_files_completed+=1;
  var new_progressbar_width=number_of_files_completed*width_per_file;
  $("#progress").css({"width":new_progressbar_width+"px", "max-width":new_progressbar_width+"px"});
}

var counter = 0;

$("#upload").click(function () {
    var fileUpload = $("#file_upload").get(0);
    var files = fileUpload.files;
    var devide = devider(files.length);
    prepare_progressbar(devide);
    for (var x = 0; x < devide; x++) {
        var fileData = new FormData();
        for (var i = 0; i < files.length / devide; i++) {
            if (counter < files.length) {
                fileData.append(files[counter].name, files[counter]);
                counter++;
            }
        }

        $.ajax({
            type: "POST",
            url: "/Upload/GetFiles",
            data: fileData,
            cache: false,
            contentType: false,
            processData: false,
            async: false,
            // On complete, it will call our update_progressbar
            complete: update_progressbar,
            success: function (result) {
                console.log(result);
            },
            error: function (xhr, status, error) { console.log('Error:' + error); },
            timeout: 0
        });
    }
});

function devider(number) {
    var count = 0;
    for (var i = 0; i < number; i+=10) {
        count++;
    }
    return count;
}