我创建了一个带有拖放功能的文件上传表单,它会递归地遍历放置的文件夹并上传文件和文件夹,并将它们添加到 JSTree 实例中。
这是删除回调
function drop(evt){
evt.stopPropagation();
evt.preventDefault();
//get selected node (created by jsTree)
var parent_id = $('#treeContainer').jstree('get_selected').attr('data-attr-itemid');
var theNodeId = $('#treeContainer').jstree('get_selected').attr('id');
for (var i=0; i<items.length; i++) {
var item = items[i].webkitGetAsEntry();
if (item) {
traverseFileTree2(item,parent_id,theNodeId);
}
}
//THIS RUNS BEFORE RECUSIVE FUNCTION IS COMPLETED
addFilesToUploadQueue(filesToQueue);
}
这是递归遍历函数
var filesToQueue = [];
function traverseFileTree2(item, parent_id, theNodeId, path) {
if (item.isFile) {
item.file(function(file){
//add parent id, and adds to array to be queued for upload
file.parent_id = parent_id;
filesToQueue.push(file);
})
return;
}
else if (item.isDirectory) {
var dirName = item.name;
var url = '<?php echo $this->Html->url(array('controller'=>'nodes', 'action'=>'addchild'));?>';
var data = {'parent_id':parent_id, 'name':dirName, 'type':'Directory'};
$.post(url,data,function(result){
//adds directory node to tree
$("#treeContainer").jstree('open_node','#'+theNodeId);
$("#treeContainer").jstree('create', '#'+theNodeId, 'last', result,null,true);
parent_id = result["attr"]["data-attr-itemid"];
theNodeId = result["attr"]["id"];
var dirReader = item.createReader();
dirReader.readEntries(function(entries) {
for (var i=0; i<entries.length; i++) {
traverseFileTree2(entries[i], parent_id, theNodeId, path + item.name + "/");
}
});
}, 'json');
}
}
我的问题是,函数 addFilesToUploadQueue(filesToQueue)
在递归异步函数 traverseFileTree2
完成之前运行。如果可以使用 Promise 来完成,我宁愿不使用回调。
最佳答案
这绝对是一种可以用 Promise 来解决的问题。
- 设计
traverseFileTree2()
,使其始终返回 promise /延迟,即使您实际上没有启动任何异步内容。- 该 Promise 的成功处理程序应提供它找到的文件列表。
- 如果您发起一堆递归调用,请列出它们的 promise 列表,并使用
$.when()
等待它们全部完成,然后再对它们进行操作.
- 类似地,在主循环中,收集顶级 Promise 列表(来自
traverseFileTree2()
),并再次使用$.when()
将它们组合起来 promise 当所有这些都结束时“完成”,汇总他们的文件列表。 (没有共享filesToQueue
变量,都是返回值。) - 设置
addFilesToUploadQueue()
在这个巨大的最后一个 promise 成功时调用,获取 promise 的文件到队列的返回数据
这是一个未经测试的重写,但即使它有缺陷,希望足以让人们理解这个想法:
function drop(evt){
evt.stopPropagation();
evt.preventDefault();
//get selected node (created by jsTree)
var parent_id = $('#treeContainer').jstree('get_selected').attr('data-attr-itemid');
var theNodeId = $('#treeContainer').jstree('get_selected').attr('id');
var promises = [];
for (var i=0; i<items.length; i++) {
var item = items[i].webkitGetAsEntry();
if (item) {
promises.push(traverseFileTree2(item,parent_id,theNodeId));
}
}
$.when(promises).then(function(filesToQueue){
addFilesToUploadQueue(filesToQueue);
});
}
和
function traverseFileTree2(item, parent_id, theNodeId, path) {
var ret = $.Deferred();
if (item.isFile) {
var files = [];
// What is .file()?? I'm assuming it's synchronous right now
item.file(function(file){
//add parent id, and adds to array to be queued for upload
file.parent_id = parent_id;
files.push(file);
});
ret.resolve(files)
} else if (item.isDirectory) {
var dirName = item.name;
var url = '<?php echo $this->Html->url(array('controller'=>'nodes', 'action'=>'addchild'));?>';
var data = {'parent_id':parent_id, 'name':dirName, 'type':'Directory'};
$.post(url,data,function(result){
var promises = [];
//adds directory node to tree
$("#treeContainer").jstree('open_node','#'+theNodeId);
$("#treeContainer").jstree('create', '#'+theNodeId, 'last', result,null,true);
parent_id = result["attr"]["data-attr-itemid"];
theNodeId = result["attr"]["id"];
var dirReader = item.createReader();
// Assuming readEntries() is syncrhonous
dirReader.readEntries(function(entries) {
for (var i=0; i<entries.length; i++) {
promises.push(traverseFileTree2(entries[i], parent_id, theNodeId, path + item.name + "/"));
}
});
$.when(promises).then(function(){
// IIRC each argument will be the return value of one of the promises
var files = [];
for(var i = 0; i < arguments.length; i++){
files.concat(arguments[i]);
}
ret.resolve(files);
},function(){
ret.fail();
});
}, 'json');
}
return ret.promise(); // .promise() is "safer" in terms of keeping code isolated
}
请注意,此示例并没有过多关注失败情况,其中一个递归目录列表恰好失败。
关于javascript - 仅在完成异步递归函数后延迟函数执行。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20129330/