[英]Detect completion of folder drop event in vanilla js
I am trying to determine if a directory tree has been fully traversed after is was dropped on a page.我试图确定在将目录树放在页面上后是否已完全遍历它。 That is: I would like to know when the next process can start after the full folder and sub-directories has been process by the drop event code.
那就是:我想知道在 drop 事件代码处理完完整文件夹和子目录后,下一个进程何时可以开始。
As an example, in the code below I want send the M.files via json to sever.作为一个例子,在下面的代码中,我想通过 json 发送 M.files 来切断。 To do this I need to know when the folder is processed.
为此,我需要知道文件夹何时被处理。 The Ajax call is not shown.
未显示 Ajax 调用。
The recursive directory tree traversal function:递归目录树遍历函数:
async function processEnt(ent,n,fls){
n = n==undefined? 0:n;
if( ent.isFile ){
fls.files.push(ent.name)
}
else if (ent.isDirectory){
fls.dirs[ent.name]={ "files":[], "dirs":{},"done":false }
var r = ent.createReader()
await r.readEntries(
async function f(ents){
if(ents.length >0){
for(var e of ents){
await processEnt(e,n+1,fls.dirs[ent.name])
}
await r.readEntries(f)
}
}
)
}
console.log(n +" level done")
}
The drop event function: drop事件函数:
async function onDrop(evt){
evt.preventDefault()
evt.stopPropagation()
M.files = {
"files":[],
"dirs":{}
}
for(item of evt.dataTransfer.items){
await processEnt( item.webkitGetAsEntry(),0,M.files )
}
console.log("on drop done")
}
I come up with a possible answer.我想出了一个可能的答案。
M.paths
hold the number of active paths and is incremented for each sub-directory past the first. M.paths
保存活动路径的数量,并且对于第一个之后的每个子目录都会增加。 The handling of files and directories has also been slightly changed.文件和目录的处理也略有变化。 A timer is used to pole the
M.paths
to see if all of the paths have been completed.计时器用于对
M.paths
进行M.paths
以查看是否所有路径都已完成。
There may exists a race condition in that the first sub-directory is processed and M.paths
is decremented before any the other directories on that level is processed.可能存在竞争条件,因为第一个子目录被处理并且
M.paths
在该级别上的任何其他目录被处理之前递减。
The drop event:掉落事件:
function onDrop(evt){
evt.preventDefault()
evt.stopPropagation()
M.paths = 0
M.files = {
"files":[],
"dirs":[]
}
for(item of evt.dataTransfer.items){
ent = item.webkitGetAsEntry()
if(ent.isFile){
M.files["files"].push(ent)
}else if(ent.isDirectory) {
M.paths+=1
processDirectory(ent,0,M.files )
}
}
window.setTimeout(function f(){
if(M.paths==0){
// drop envent processed
//run update or send info to server
console.log("Drop event done")
}else{
window.setTimeout(f,500)
}
},500)
}
Function to process each directory:处理每个目录的函数:
function processDirectory(ent,n,fls){
n = n==undefined? 0:n;
var new_dir ={"ent":ent,"files":[],"dirs":[]}
fls["dirs"].push(new_dir)
var r = ent.createReader()
r.readEntries(
function f(ents){
var leaf = true
var add_path =0
for(let entc of ents){
if ( entc.isDirectory ){
M.paths+= add_path
add_path = 1
console.log(n+":"+M.paths+":"+entc.name)
leaf = false
processDirectory(entc,n+1,new_dir)
}else if( entc.isFile){
new_dir["files"].push(ent)
}
}
if(leaf){ M.paths--}
}
)
}
This seems to work though I have not tested it thoroughly.这似乎有效,尽管我还没有对其进行彻底的测试。 Also if there are many entries it will not get all of them.
此外,如果有很多条目,则不会获得所有条目。 See https://stackoverflow.com/a/53058574/2975893 for details.
有关详细信息,请参阅https://stackoverflow.com/a/53058574/2975893 。
I found a solution which seems to do the trick.我找到了一个似乎可以解决问题的解决方案。
The drop event function: drop事件函数:
function onDrop (evt){
evt.preventDefault()
evt.stopPropagation()
var promises = []
for(item of evt.dataTransfer.items){
//create new Promise that calls processItem function
// the promise is used to track if the work is complete
var p = new Promise( function(res, rej){
processItem(item.webkitGetAsEntry(),res,rej)
})
// record each promise
promises.push( p )
}
// the drop event is complete when all of the item (child)
// promises are completed
Promise.all( promises ).then(function(){
// code for after the drop event
})
}
The function that processes each item function processItem (item,res,rej){处理每个item的函数 function processItem(item,res,rej){
if (ent.isFile){
//handle file entry
//complete this items promise
res()
}
else if (ent.isDirectory){
var promises = []
var dirReader = ent.createReader()
function read( entries ){
if (entries.length > 0 ){
for(var e of entries){
var p = new Promise( function(resm,rejm) {
processItem(e,resm,rejm)
})
promises.push(p)
}
/*
"readEntries" called again to ensure all entries are read as
"readEntries" does not read all files when there
is a large amount of files
*/
dirReader.readEntries(read)
}
}
else{
/*
if there are no more entries ensure all entries
in the directory are processed
*/
Prmoise.all( promises ).then(function(){
// once all promises are complete complete this items promise
res()
})
}
// start the read process
dirReader.readEntries(read)
}
}
In testing all processes completed before their parents.在测试之前完成所有进程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.