在做上传文件的时候,想要在上传时把每个文件的进度条显示出来,于是找到了addEventListener这个方法,这里记录一下在实现进度条的过程中遇到的坑。
直接上JS代码
var files = $("#upload")[0].files for (var i = 0; i < files.length; i++ ) { var formData = new FormData(); formData.append("file", files[i]); $.ajax({ url: url, type: 'POST', data: formData, processData: false, contentType: false, xhr: function() { var xhr = new XMLHttpRequest(); //使用XMLHttpRequest.upload监听上传过程,注册progress事件,打印回调函数中的event事件 xhr.upload.addEventListener('progress', function(e){ var progressRate = Math.round((e.loaded / e.total) * 100) + '%'; //通过设置进度条的宽度达到效果 console.log(`fileName:', files[i].name, uploaded:', progressRate); }); return xhr; }, success: function (arg) { console.log(arg) }, error : function (responseStr) { console.log(responseStr.responseJSON) continue } }); }
出现的问题:
刚开始用以上代码执行上传多个文件,:xhr 中的 files[i].name 不正确,例如我上传文件 a.jpg b.jpg c.jpg ,最后的输出结果都是 fileName:c.jpg uploaded: xx%
原因是:
xhr:中的 files[i].name 受循环的影响,无论有循环多少次,这里的i总是显示最后循环的一个数。
解决方法一:
将for循环中的var i 换成 let i,这样在下面的循环中,每个循环都会使用各自的i,不会受循环的影响从而改变i的值。
解决方法二:
把 ajax 的代码放在一个闭包里,将i作为参数传入。
var files = $("#upload")[0].files for (var i = 0; i < files.length; i++ ) { function upload(){ var formData = new FormData(); formData.append("file", files[i]); function close(i){ $.ajax({ url: url, type: 'POST', data: formData, processData: false, contentType: false, xhr: function() { var xhr = new XMLHttpRequest(); xhr.upload.addEventListener('progress', function(e){ var progressRate = Math.round((e.loaded / e.total) * 100) + '%'; //通过设置进度条的宽度达到效果 console.log(`fileName:', files[i].name, uploaded:', progressRate); }); return xhr; }, success: function (arg) { console.log(arg) }, error : function (responseStr) { console.log(responseStr.responseJSON) } }); } return close } close = upload(); close(i); }