Javascript文件拖放和读取目录-异步递归
所以我尝试创建一个文件拖放web应用程序。现在,用户可以在屏幕上放置文件,我可以读取这些文件,包括已放置目录中的所有文件。但是,我不知道脚本何时读取完文件 一些代码: 第一个函数处理一个“drop”事件,并将循环遍历每个文件,并将其发送给另一个将读取其内容的函数Javascript文件拖放和读取目录-异步递归,javascript,drag-and-drop,html5-filesystem,Javascript,Drag And Drop,Html5 Filesystem,所以我尝试创建一个文件拖放web应用程序。现在,用户可以在屏幕上放置文件,我可以读取这些文件,包括已放置目录中的所有文件。但是,我不知道脚本何时读取完文件 一些代码: 第一个函数处理一个“drop”事件,并将循环遍历每个文件,并将其发送给另一个将读取其内容的函数 function readDrop( evt ) { for( var i = 0; i < evt.dataTransfer.files.length; i++) { var entry = ev
function readDrop( evt )
{
for( var i = 0; i < evt.dataTransfer.files.length; i++)
{
var entry = evt.dataTransfer.items[i].webkitGetAsEntry();
if(entry)
readContents(entry, "");
}
//Do stuff after all files and directories have been read.
}
我不确定该从这里走到哪里,以便在读取所有文件和目录后可以进行回调。文件系统API似乎不太适合执行完全递归遍历任务,这可能是其他供应商不采用它的部分原因。无论如何,通过一系列神秘的承诺,我认为我能够实现这个目标:
function traverse_directory(entry) {
let reader = entry.createReader();
// Resolved when the entire directory is traversed
return new Promise((resolve_directory) => {
var iteration_attempts = [];
(function read_entries() {
// According to the FileSystem API spec, readEntries() must be called until
// it calls the callback with an empty array. Seriously??
reader.readEntries((entries) => {
if (!entries.length) {
// Done iterating this particular directory
resolve_directory(Promise.all(iteration_attempts));
} else {
// Add a list of promises for each directory entry. If the entry is itself
// a directory, then that promise won't resolve until it is fully traversed.
iteration_attempts.push(Promise.all(entries.map((entry) => {
if (entry.isFile) {
// DO SOMETHING WITH FILES
return entry;
} else {
// DO SOMETHING WITH DIRECTORIES
return traverse_directory(entry);
}
})));
// Try calling readEntries() again for the same dir, according to spec
read_entries();
}
}, errorHandler );
})();
});
}
traverse_directory(my_directory_entry).then(()=> {
// AT THIS POINT THE DIRECTORY SHOULD BE FULLY TRAVERSED.
});
根据drarmstr的回答,我修改了该函数以符合Airbnb ESLint标准,并希望对其用法和结果作进一步的评论 以下是新功能:
function traverseDirectory(entry) {
const reader = entry.createReader();
// Resolved when the entire directory is traversed
return new Promise((resolve, reject) => {
const iterationAttempts = [];
function readEntries() {
// According to the FileSystem API spec, readEntries() must be called until
// it calls the callback with an empty array. Seriously??
reader.readEntries((entries) => {
if (!entries.length) {
// Done iterating this particular directory
resolve(Promise.all(iterationAttempts));
} else {
// Add a list of promises for each directory entry. If the entry is itself
// a directory, then that promise won't resolve until it is fully traversed.
iterationAttempts.push(Promise.all(entries.map((ientry) => {
if (ientry.isFile) {
// DO SOMETHING WITH FILES
return ientry;
}
// DO SOMETHING WITH DIRECTORIES
return traverseDirectory(ientry);
})));
// Try calling readEntries() again for the same dir, according to spec
readEntries();
}
}, error => reject(error));
}
readEntries();
});
}
下面是一个drop事件处理程序:
function dropHandler(evt) {
evt.preventDefault();
const data = evt.dataTransfer.items;
for (let i = 0; i < data.length; i += 1) {
const item = data[i];
const entry = item.webkitGetAsEntry();
traverseDirectory(entry).then(result => console.log(result));
}
}
函数dropHandler(evt){
evt.preventDefault();
const data=evt.dataTransfer.items;
对于(设i=0;iconsole.log(result));
}
}
末尾的result
变量包含一个数组,反映了拖放文件夹的树结构
例如,下面是我自己网站的git repo,通过上面的代码运行:
这是供比较的Git repo有趣的一点是您在注释处遗漏的代码//阅读文件-向我们展示该代码,我们可能会帮助您好吧,我想我不认为代码的这一部分有那么重要,但我补充了一点您是现代英雄
function traverseDirectory(entry) {
const reader = entry.createReader();
// Resolved when the entire directory is traversed
return new Promise((resolve, reject) => {
const iterationAttempts = [];
function readEntries() {
// According to the FileSystem API spec, readEntries() must be called until
// it calls the callback with an empty array. Seriously??
reader.readEntries((entries) => {
if (!entries.length) {
// Done iterating this particular directory
resolve(Promise.all(iterationAttempts));
} else {
// Add a list of promises for each directory entry. If the entry is itself
// a directory, then that promise won't resolve until it is fully traversed.
iterationAttempts.push(Promise.all(entries.map((ientry) => {
if (ientry.isFile) {
// DO SOMETHING WITH FILES
return ientry;
}
// DO SOMETHING WITH DIRECTORIES
return traverseDirectory(ientry);
})));
// Try calling readEntries() again for the same dir, according to spec
readEntries();
}
}, error => reject(error));
}
readEntries();
});
}
function dropHandler(evt) {
evt.preventDefault();
const data = evt.dataTransfer.items;
for (let i = 0; i < data.length; i += 1) {
const item = data[i];
const entry = item.webkitGetAsEntry();
traverseDirectory(entry).then(result => console.log(result));
}
}