【问题标题】:Callbacks in Aysncronous Recursive Methods?Aysncronous 递归方法中的回调?
【发布时间】:2017-02-05 19:35:27
【问题描述】:

对于我正在做的一个项目,我有一个基于文件及其内容构造树模型的函数。我的解析文件函数是递归的,并且会继续调用它自己,直到它不能在目录树中更深入/点击一个不包含更多文件的文件。但是我不知道如何为此函数设置回调,因为它是递归的。截至目前,我只是让我的构造树方法超时,但这对我的问题来说是一个可怕且不可靠的解决方案。这是我的代码:

function constructTree(dir){
  tree = new TreeModel()
  root = tree.parse({name: 'Marshall McGee Sample Pack'});
  parseFiles(dir, root, tree);
  setTimeout(function(){
    root.all().forEach(function(node){
      console.log(node.model.name);
    });
  }, 1000)
}

function parseFiles(dir, parrent, tree){
  fs.readdir(dir, function(err, files){
     if(files){
       for(i = 0; i < files.length; i++){
          parrent.addChild(tree.parse({name: files[i]}));
          console.log(files[i]);
          parseFiles(dir + "/" + files[i], parrent, tree);
       }
     }
  });
}

此代码“有效”但非常糟糕。我不知道如何确定我是否搜索了整个目录,或者如何正确地执行此操作。我希望我解释得很好!谢谢,任何帮助都被应用了!!!

【问题讨论】:

  • 回调函数是什么意思?
  • 我添加了javascript 标签,缺少该标签可以解释为什么您到现在都没有得到任何答案。

标签: javascript recursion callback tree


【解决方案1】:

您应该向 parseFiles 函数添加一个回调参数,并让它在完成其工作时调用该回调(异步)。

为了知道某个文件夹中的所有项目何时被遍历,你应该保持计数,只有当最后一个完成时,通知调用者(通过他提供的回调)树已完成(请参阅count 变量):

function constructTree(dir){
  var tree = new TreeModel()
  var root = tree.parse({name: 'Marshall McGee Sample Pack'});
  // instead of timer, pass a callback function that should be called
  // when the whole tree has been loaded.
  parseFiles(dir, root, tree, function () {
    root.all().forEach(function(node){
      console.log(node.model.name);
    });
  });
}

function parseFiles(dir, parrent, tree, done){
  fs.readdir(dir, function(err, files){
     // Only proceed here when there is at least one file (added condition)
    if(files && files.length){
      // keep track how many items still need to be collected:
      var count = files.length;
      for(var i = 0; i < files.length; i++){
        parrent.addChild(tree.parse({name: files[i]}));
        console.log(files[i]);
        parseFiles(dir + "/" + files[i], parrent, tree, function () {
          count--;
          // if we have all items (recursively) added to the tree, notify the caller
          if (!count && done) done();
        });
      }
    } else {
      // If no information in this folder, notify caller immediately
      if (done) done();
    }
  });
}

由于调用者没有义务传递回调,代码必须在调用之前检查done 的值。这就是为什么会有if (done) done()

注意:与您的问题无关,但您应注意使用var 关键字(或letconst)以避免不必要地创建全局变量。

【讨论】:

    【解决方案2】:

    每个函数调用都放在堆栈上。

    Step 1: constructTree 
    Step 2: calls parseFiles
    Step 3: calls parseFiles
    .
    .
    .
    Step n-1: calls parseFiles
    Step n: cannot parse any further
    

    此时,它将开始返回

    Step n-1
    Step n-2
    .
    .
    .
    Step 3
    Step 2
    Step 1 - and pointer returns to the original caller
    

    如果这解决了问题或者您有不同的顾虑,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-30
      • 2023-04-10
      • 2014-09-10
      • 2022-11-10
      • 1970-01-01
      • 2016-08-03
      相关资源
      最近更新 更多