如何通过querySelector获取正确的文件数量?遇数量翻倍问题
问题描述
用JavaScript的querySelector处理HTML文件输入框的图片时,遇到了一个奇怪的问题:实际选1张图片,代码里却识别出2张;选多张的话,数量直接翻倍。用console.log排查了半天,没找到问题出在哪。
代码示例
HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Test</title> </head> <body> <form id="load"> <input type="file" accept="image/*" multiple> <br> <button type="submit">Upload</button> </form> <script src="https://cdnjs.cloudflare.com/ajax/libs/compressorjs/1.0.7/compressor.min.js"></script> <script src="index.js"></script> </body> </html>
JavaScript代码
window.addEventListener('click', function () { const form = document.querySelector('form') form.addEventListener('submit', function (e) { e.preventDefault() let files = form.querySelector('[type="file"]').files const promises = [] console.log(files) for (let file of files) { console.log("Here!!!") promises.push(new Promise(function (resolve, reject) { new Compressor(file, { quality: 0.6, success(result) { //TODO console.log("success") }, error(err) { console.log(err.message) reject() }, }) })) } }) })
问题原因与修复
问题根本不是querySelector的问题,而是你给window绑了click事件,每次点击页面都会给form新增一个submit事件监听器。比如你点一次提交按钮,之前已经绑定了两次submit事件,那代码就会执行两次,循环也跑两次,看起来就是文件数量翻倍了。
直接去掉外层的window.click监听,直接给form绑定submit事件就行:
修改后的JS代码:
const form = document.querySelector('form') form.addEventListener('submit', function (e) { e.preventDefault() let files = form.querySelector('[type="file"]').files const promises = [] console.log(files) for (let file of files) { console.log("Here!!!") promises.push(new Promise(function (resolve, reject) { new Compressor(file, { quality: 0.6, success(result) { // 别忘了调用resolve,不然Promise会一直处于pending状态 resolve(result) console.log("success") }, error(err) { console.log(err.message) reject(err) }, }) })) } // 如果需要等所有压缩完成再做后续操作,可以加这段 // Promise.all(promises).then(compressedFiles => { // console.log('所有图片压缩完成', compressedFiles) // // 在这里处理上传逻辑 // }).catch(err => { // console.log('压缩失败', err) // }) })
另外提个小细节:原代码里的Promise在success回调里没调用resolve,这样Promise会一直挂着,建议加上,方便后续用Promise.all处理所有压缩结果。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

