Javascript 如何知道递归函数已结束

Javascript 如何知道递归函数已结束,javascript,json,recursion,Javascript,Json,Recursion,我有一个递归函数,它遍历所有目录并将bmp文件放入JSON数组中,其中键或文件夹以及子数组是每个文件夹的内容(我不知道是否清楚)。例如,此文件系统: -数据/ |-你好/ |-j.bmp |-t.bmp -嗯/ |-c.bmp 我会给出这样的信息: {"data":{ "hello":{ "j.bmp":"j.bmp" }, "t.bmp":"t.bmp" }, "ok":{ "c.bmp":"c.bmp" } } 这是我的代码: fu

我有一个递归函数,它遍历所有目录并将bmp文件放入JSON数组中,其中键或文件夹以及子数组是每个文件夹的内容(我不知道是否清楚)。例如,此文件系统:

-数据/
|-你好/
|-j.bmp
|-t.bmp
-嗯/
|-c.bmp
我会给出这样的信息:

{"data":{
    "hello":{
      "j.bmp":"j.bmp"
    },
    "t.bmp":"t.bmp"
  },
  "ok":{
    "c.bmp":"c.bmp"
  }
}
这是我的代码:

function preload(res_dir, nextfunc, errorfunc){
  let images = {}
  let c = document.createElement("CANVAS");

  function travelDir(directory){
    let dirReader = directory.createReader();
    dirReader.readEntries(function(subdirs){
      subdirs.forEach(function(entry){
        if (entry.isDirectory){
          let path = entry.toURL().replace(res_dir.toURL(),"").split("/");
          let a = images;
          for (var i = 0; i < path.length - 2; i++){
            a = a[path[i]];
          }
          a[entry.name] = {};
          travelDir(entry);
        } else if (entry.name.substr(entry.name.length - 4, 4) == ".bmp"){
          loadres(entry);
        }
      });
    }, errorfunc);
  }

  travelDir(res_dir);

  function loadres(file){
    let a = images;
    let path = file.toURL().replace(res_dir.toURL(),"").split("/");
    for (var i = 0; i < path.length - 1; i++){
      a = a[path[i]];
    }
    a[file.name] = file.name;
  }
}
函数预加载(res_dir,nextfunc,errorfunc){
让图像={}
设c=document.createElement(“画布”);
函数travelDir(目录){
让dirReader=directory.createReader();
dirReader.readEntries(函数(subdirs){
子目录forEach(函数(条目){
if(条目.isDirectory){
让path=entry.toURL().replace(res_dir.toURL(),“”)。拆分(“/”;
设a=图像;
对于(var i=0;i
travelDir函数从res_dir开始遍历所有目录,当它是一个目录时创建密钥,否则调用loadres,将文件名添加到JSON数组
images

这很有效,但是我如何知道这些函数何时遍历所有目录?
(如果需要,我需要在整个过程结束时执行函数
nextfunc
,将
images
作为参数,当它包含整个文件树时)

因为您的代码是异步的,递归不容易管理。您不能仅仅从自身内部调用
travelDir
,因为父函数只有在子函数完成时才完成,而这不是您调用它的时候

如果工具链已启用ES7,则只需使用
async/await
,即:

async function travelDir(directory) {
    .... await travelDir(subdir)
}

await travelDir(root)
nextfunc()
否则,与其直接生成子项,不如将其放入队列中,并使用回调处理队列中的下一项,并在其为空时调用
nextfunc
,方法如下:

let queue = [];

function step() {
    if (!queue.length)
        nextfunc(); // <-- ends here
    else
        travelDir(queue.shift())
}

function travelDir(directory) {
    ...
    dirReader.readEntries(parseEntries, errorfunc);
}

function parseEntries(subdirs) {
    subdirs.forEach(function (entry) {
        if (entry.isDirectory)
            queue.push(entry);
        else ...
            loadres(entry);
    });
    step() // <-- indirect recursion
}

queue.push(res_dir)
step()
let queue=[];
函数步骤(){
如果(!queue.length)

nextfunc();//当第一个调用返回时,我猜:-)@leaf:nope,因为
dirReader.readEntries
是异步的。事实上,当第一个调用返回时,我只有一个res_dir的子目录列表:travelDir函数只执行一次,对于resu dir,谢谢,我不知道Javascript中有异步,但这是有意义的。我将尝试这些和解!