Javascript 仅在完成异步递归函数后延迟函数执行。

Javascript 仅在完成异步递归函数后延迟函数执行。,javascript,recursion,promise,Javascript,Recursion,Promise,我用拖放创建了一个文件上传表单,它递归地遍历被删除的文件夹,上传文件和文件夹,并将它们添加到JSTree实例中 这是回拨电话 function drop(evt){ evt.stopPropagation(); evt.preventDefault(); //get selected node (created by jsTree) var parent_id = $('#treeContainer').jstree('get_selected').attr(

我用拖放创建了一个文件上传表单,它递归地遍历被删除的文件夹,上传文件和文件夹,并将它们添加到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);
}
功能下降(evt){
evt.stopPropagation();
evt.preventDefault();
//获取所选节点(由jsTree创建)
var parent_id=$('#treeContainer').jstree('get_selected').attr('data-attr-itemid');
var theNodeId=$('#treeContainer').jstree('get#u selected').attr('id');
对于(var i=0;i’;
变量数据={'parent\u id':parent\u id,'name':dirName,'type':'Directory'};
$.post(url、数据、函数(结果){
//将目录节点添加到目录树
$(“#treeContainer”).jstree('open#u node','#'+节点ID);
$(“#treeContainer”).jstree('create','#'+节点ID,'last',result,null,true);
父项id=结果[“属性”][“数据属性项id”];
theNodeId=result[“attr”][“id”];
var dirReader=item.createReader();
dirReader.readEntries(函数(条目){

对于(var i=0;i,这绝对是你可以用承诺来解决的问题

  • 设计
    traverseFileTree2()
    ,使其始终返回承诺/延迟,即使您实际上没有启动任何异步操作。
    • promise的成功处理程序应该提供它找到的文件列表
    • 如果启动一组递归调用,请列出它们的承诺,并使用
      $.when()
      等待它们全部完成,然后再对它们执行操作
  • 类似地,在主循环中,收集顶级承诺的列表(从
    traverseFileTree2()
    ),然后再次使用
    $。when()
    将它们组合成一个承诺,当所有承诺都结束时,“完成”,聚合它们的文件列表。(没有共享的
    filesToQueue
    变量,都是返回值。)
  • addFilesToUploadQueue()
    设置为在这个巨大的最后承诺成功时调用,将承诺的文件返回数据带到队列中

  • 这里有一个未经测试的重写,但即使它有足够的缺陷,希望能让大家理解这个想法:

    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);         
        });   
    }
    
    功能下降(evt){
    evt.stopPropagation();
    evt.preventDefault();
    //获取所选节点(由jsTree创建)
    var parent_id=$('#treeContainer').jstree('get_selected').attr('data-attr-itemid');
    var theNodeId=$('#treeContainer').jstree('get#u selected').attr('id');
    var承诺=[];
    for(var i=0;i.file()是异步的
    
    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
    }