You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 20:01:33