Программно меняющееся значение типа входного файла? - PullRequest
1 голос
/ 13 марта 2019

Я пытаюсь создать немного кода, который я могу использовать на своем сайте, который по сути является средством выбора / выбора фотографий с некоторой проверкой.Вот мой код:

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 второго и т. д. При каждом выборе файлы из предыдущего добавляются в окончательный список, ноне файлы из последнего выбора.

1 Ответ

3 голосов
/ 13 марта 2019

Я думаю, проблема в том, что вы ожидаете, что

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

get выполняется перед тем, как назначить действительные файлы для this.output.files.

Но 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);
    }

    // ...
}
...