首页 > 解决方案 > JavaScript:无法将 for 循环的索引与另一个数字进行比较

问题描述

我创建了两个按钮:

<input id="myfile" type="file" name="files[]" multiple="multiple" >
<input id="mysubmit" type="submit" value="Upload">

使用以下js:

$("#mysubmit").click(function() {
    var bucket = new AWS.S3({params: {Bucket: 'mybucket'}});
    var files_arr= $('#myfile').prop("files")
    var ErrNum = 0;
    for (var i=0; i<files_arr.length; i++){
        var params = {Key: files_arr[i].name, ContentType: files_arr[i].type, Body: files_arr[i]};
        bucket.upload(params).on('httpUploadProgress', function(evt) {
               console.log("Uploaded :: " + parseInt((evt.loaded * 100) / evt.total)+'%');
        }).send(function(err, data) {
           if (err){
              ErrNum++;
           }
        });
        if (i === files_arr.length-1 && ErrNum > 0) {
           //do something
        }
        if (i === files_arr.length-1 && ErrNum === 0){
           alert("Success!");
        }
    };                     
});

我想等到最后一个元素上传并尝试检查上传文件期间发生了多少错误。

但是,if 语句不起作用,因为首先会提示成功,然后会在控制台中显示错误。

我也在 for 循环之外尝试过这样的事情:

if (ErrNum>0){
   //do something
}else{
   alert("Success!");
}

这也不起作用。

标签: javascript

解决方案


这是因为上传方法是异步的。2 if 语句将首先执行。如果你把它放在回调中,它可能会也可能不会起作用。因为当你的循环结束时,一个可能首先完成(不是最后一个)。

你应该看看 async、await 或 Promise 并阅读相关内容。

我认为这应该是如何实现它的一个例子:

var bucket = new AWS.S3({params: {Bucket: 'mybucket'}});

function upload(params) {
    return new Promise((resolve, reject) => {
        bucket.upload(params).on('httpUploadProgress', function(evt) {
            console.log("Uploaded :: " + parseInt((evt.loaded * 100) / evt.total)+'%');
        }).send(function(err, data) {
            if (err){
                reject(err);
            }
            else {
                resolve();
            }
        });
    });
}

$("#mysubmit").click(async function() {
    var files_arr= $('#myfile').prop("files");
    var ErrNum = 0;
    for (var i=0; i<files_arr.length; i++){
        var params = {Key: files_arr[i].name, ContentType: files_arr[i].type, Body: files_arr[i]};

        //try the upload function if it failes, catch it
        try {
            //await for upload to finish
            await upload(params);
        }
        catch (e) {
            //increment ErrNum if upload failed.
            ErrNum++;
        }

        if (i === files_arr.length-1 && ErrNum > 0) {
            //do something
        }
        else if (i === files_arr.length-1 && ErrNum === 0){
            alert("Success!");
        }
    }

    //I think it is more efficient if you put your if statements here
    if (ErrNum > 0) {
        //do something
    }
    else {
        alert("Success!");
    }
});

如果您阅读了有关 Promises 的内容并了解使用 Promises.all() 一次完成所有上传会更有效;

我希望这会有所帮助,祝你好运!


推荐阅读