【问题标题】:Programmatically changing value of input type file?以编程方式更改输入类型文件的值?
【发布时间】:2019-03-13 12:03:04
【问题描述】:

我正在尝试生成一些可以在整个网站中重复使用的代码,它本质上是一个带有一些验证的照片选择器/选择器。这是我的代码:

class PhotoPicker
{
    constructor(element)
    {
        this.element = element;

        //Creating needed HTML Markup
        this.createMarkUp();

        //FileList of valid data.
        this.validFiles = new DataTransfer();

        //Initialise Picker.
        this.input.onchange = () => {
            this.updateOutput();
            this.output.files = this.validFiles.files;
        }
    }

    updateOutput()
    {
        const files = Array.from(this.input.files);
        files.forEach((file) => {                
            let reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = () => {
                photo = this.createPhotoThumb({
                    url : reader.result,
                    name: file.name,
                    size: file.size
                });
                if (this.validatePhoto(file)) {
                    this.validFiles.items.add(file);
                };
            };
        });
    }

    createMarkUp()
    {
        //Creating needed HTML Markup
    }
    createPhotoThumb(data = {})
    {
        //Creating a photo thumbnail for preview
    }
    validatePhoto(photo)
    {
        //Validating the photo
    }
}

发生的情况是,当我第一次选择一些图像时,会显示缩略图并更新有效文件列表this.validFiles.files,但不是最终列表我计划将其发送到服务器 this.output.files然而,在第二次尝试时,它可以工作!最终列表将使用第一个选择中的文件进行更新,NOT 第二个,依此类推.. 每次选择时,前一个选择中的文件都会添加到最终列表中列出但不列出上次选择的文件。

【问题讨论】:

  • Class 应该是小的c 我认为
  • 这是constructor 而不是constrctor
  • 是的,两者都是真的,抱歉打错了.. 有什么关于逻辑的吗?问题本身?
  • FileReader#onload 是异步的。添加一些日志记录,您会发现 this.createPhotoThumb 仅在您的 forEach 循环完成后才被调用(方式)
  • 为什么要创建文件的 dataURI 版本?如果您只想显示它,请使用 blob URI,您可以使用 URL.createObjectURL(blob) 同步创建它。

标签: javascript html input filelist


【解决方案1】:

我认为问题在于你期望那个

reader.onload = () => {
    photo = this.createPhotoThumb({
        url : reader.result,
        name: file.name,
        size: file.size
    });
    if (this.validatePhoto(file)) {
        this.validFiles.items.add(file);
    };
};

在将有效文件分配给this.output.files之前执行get。

但是reader.onload 会异步执行,因此您将有效文件分配给this.output.files 会在有效文件添加到有效文件数组之前执行。

您必须实现一些逻辑来等待读者的onload 处理程序的完整性。

这将是一个可能的解决方案:

class PhotoPicker
{
    constructor(element)
    {
        this.element = element;

        // Creating needed HTML Markup
        this.createMarkUp();

        // FileList of valid data.
        this.validFiles = new DataTransfer();

        // Initialise Picker.
        this.input.onchange = () => {
            this.updateOutput()
                .then(() => {
                    this.output.files = this.validFiles.files;
                });
        }
    }

    updateOutput()
    {
        const files = Array.from(this.input.files);
        const fileLoaderPromises = [];
        files.forEach((file) => {
            const promise = new Promise((resolve) => {
                let reader = new FileReader();
                reader.readAsDataURL(file);
                reader.onload = () => {
                    photo = this.createPhotoThumb({
                        url : reader.result,
                        name: file.name,
                        size: file.size
                    });
                    if (this.validatePhoto(file)) {
                        this.validFiles.items.add(file);
                    };
                    // Mark the file loader as "done"
                    resolve();
                };
            })

            // Add the promise to the list of file loader promises
            fileLoaderPromises.push(promise);
        });

        // Return a promise which resolves as soon as all file loader promises are done
        return Promise.all(fileLoaderPromises);
    }

    // ...
}

【讨论】:

  • 代码审查,而不是forEach,使用Promise.all(files.filter().map((file) => ...)) 理想情况下,每个promise都会返回内容而不是直接从该代码修改类状态,解决promise的代码应该执行设置...将使代码更容易理解
  • 是的……就是这样!我相信我在异步/同步操作方面的有限知识是让我陷入困境的原因。谢谢大家..现在我知道我的下一课应该是什么了:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-21
  • 2011-12-27
  • 1970-01-01
  • 1970-01-01
  • 2014-09-11
  • 1970-01-01
  • 2018-06-20
相关资源
最近更新 更多