Такое ощущение, что вы делаете вещи слишком сложными, и я предлагаю еще одно хорошее прочтение стандартов кодирования и способа работы Promises :) Конструкция async / await была введена для повышения читабельности кода.
В любом случае, у меня есть некоторый непроверенный код здесь. Но это должно сработать. Также я настоятельно советую вам добавить набор текста. Вы используете angular, поэтому я могу только предположить, что вы используете TypeScript. При наборе текста вы будете делать меньше ошибок, и компилятор поможет вам в этом.
Прежде чем я приведу код, этот webkitGetAsEntry
не является стандартным. Его следует использовать только в том случае, если вы действительно не хотите использовать старые браузеры или safari / ios:
Нестандартные. Эта функция нестандартна и не соответствует стандартам. Не используйте его на рабочих сайтах, выходящих в Интернет: он не будет работать для каждого пользователя. Также могут быть большие несовместимости между реализациями, и поведение может измениться в будущем.
Но вы можете go об этом так. Первая функция для обработки события. Второй пересечь дерево:
async dndDropFiles(event: DragEvent): Promise<void> {
if (event.dataTransfer.types[0] !== "Files" || !event.dataTransfer.items) {
return;
}
const entries = [...(event.dataTransfer.items as any)].map(
item => item.webkitGetAsEntry()
);
const allEntries = await this.dndTraverseFileTree(entries);
const files = await Promise.all(
allEntries.map(
(entry) => new Promise((resolve, reject) => entry.file(resolve, reject))
)
);
this.files = new Set(files);
if (this.files.size > 0) {
this.progress = this.uploadService.upload(
this.files, this.currentDir, this.currentProject
);
}
}
async dndTraverseFileTree(entries: any[]): Promise<any[]> {
const dirs = entries.filter(entry => !!entry && entry.isDirectory);
const files = entries.filter(entry => !!entry && entry.isFile);
if (dirs.length) {
const childEntries = (
await Promise.all(
dirs.map(dir => new Promise(
(resolve, reject) => dir.createReader().readEntries(resolve, reject))
)
)
).flat();
return this.dndTraverseFileTree(childEntries);
}
return [ ...files ];
}