#javascript #html #input #filelist
#javascript #HTML #ввод #список файлов
Вопрос:
Я пытаюсь создать фрагмент кода, который я могу повторно использовать на своем сайте, который, по сути, является средством выбора фотографий с некоторой проверкой. Вот мой код:
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
, однако со второй попытки это работает! где окончательный список обновляется файлами из первого выбора, а НЕ из второго, и так далее .. при каждом выборе файлы из предыдущего добавляются в окончательный список, но не файлы из последнего выбора.
Комментарии:
1.
Class
должно быть с небольшимc
, я думаю2. Это
constructor
и неconstrctor
3. Да, оба верны, извините за опечатку.. что-нибудь о логике, хотя? в чем сама проблема?
4. FileReader#onload выполняется асинхронно. Добавьте немного протоколирования, и вы поймете, что это
this.createPhotoThumb
вызывается (way) только после завершения вашегоforEach
цикла5. Почему вы создаете версию файла dataURI? Если вы хотите только удалить его, то используйте URI большого двоичного объекта, который вы можете создавать синхронно с помощью
URL.createObjectURL(blob)
.
Ответ №1:
Я думаю, проблема в том, что вы ожидаете, что
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);
}
// ...
}
Комментарии:
1. Проверка кода, вместо
forEach
используйтеPromise.all(files.filter().map((file) => ...))
, И в идеале каждое обещание возвращало бы содержимое вместо изменения состояния класса непосредственно из этого кода, настройку должен выполнять код, который разрешает обещание… это значительно упростит обработку кода2. ДА … так оно и было! Я полагаю, что мои ограниченные знания в асинхронных / синхронных операциях были причиной, из-за которой я застрял там. Спасибо, ребята.. теперь я знаю, каким должен быть мой следующий урок 🙂