NodeJS 在express get()中正确调用下一个回调

bsxbgnwa  于 2023-05-28  发布在  Node.js
关注(0)|答案(1)|浏览(109)

我有一个运行在nodejs上的express服务器。我有一个文件结构,我想把它变成一个链接列表。我已经包括了我的递归文件结构函数。
文件结构函数

function fileTreeWrapper (root, callback) {
    output = recursiveFileTree(root);
    console.log(output);
    callback();
}

function recursiveFileTree (root) {
    fs.readdir('./' + root, function (err, files) {
        if(err) throw err;
        var structure = '';
        var folders = '';
        var tests = '';

        structure += '<ul>';
        
        for(var i in files) {
            if(files[i].indexOf('.') === -1) {
                folders += '<li id="folder">' + root + '/' + files[i] + '">' + files[i].charAt(0).toUpperCase() + files[i].slice(1);
                folders += recursiveFileTree(root + '/' + files[i]);
                folders += '</li>';
            } else if (files[i].indexOf('.js') > -1) {
                tests += '<li id="file"><a href="' + root + '/' + files[i] + '">' + files[i] + '</a></li>';
            }
        }
        structure += folders;
        structure += tests;
        structure += '</ul>';
        return structure;
    });
}

我打电话给路由器。得到这样的:

router.get('/', [function (req, res, next) {
    fileTreeWrapper('rootFolder', function() {
        next();
    });
}, function (req, res) {
    res.render('Files & Folders', {
        title: 'Main',
        localTitle: 'Choose a File',
        result: output
    }, function (err, html) {
        if(err) throw err;
        res.send(html);
        res.end();
    });
}]);

然而,当我运行这个时,我的页面显示为空白。我的玉模板渲染看起来像这样:

h1= title
h3= localTitle
div !{result}

我是否使用了不恰当的next()回调函数?为什么这行不通?

zlwx9yxi

zlwx9yxi1#

你最初做的事情有相当大的错误。我重写了你所有的代码让它更有意义。希望这能帮上忙。

function recursiveFileTree(root, callback) {
  fs.readdir('./' + root, function (err, files) {
    if (err) { return callback(err); }
    try {
      var structure = '';
      var folders = '';
      var tests = '';
      structure += '<ul>';
      files.forEach(function (file) {
        if (file.indxOf('.') === -1) {
          folders += '<li id="folder">' + root + files[i] + '">' + file.charAt(0).toUpperCase() + file.slice(1);
          folders += recursiveFileTree(root + '/' + file);
          folders += '</li>';
        } else {
          tests += '<li id="file"><a href="' + root + '/' + file + '">' + file + '</a></li>';
        }
      });
      structure += folders;
      structure += tests;
      structure += '</ul>';
      callback(null, structure);
    } catch (err) {
      return callback(err);
    }
  })
};

router.get('/', function (req, res) {
  recursiveFileTree('rootFolder', function (err, structure) {
    if (err) { throw err; }
    res.render('fileListingView', {
      title: 'Main',
      localTitle: 'choose a File',
      result: structure
    });
  });
});

注意事项:

  • 看起来您甚至不需要使用中间件函数(获取next作为参数的函数)。把中间件想象成一个管道。req按顺序通过每个中间件(管道的一部分),直到它遇到最终的处理程序(最终调用res.sendres.jsonres.render的处理程序)。
  • 调用res.render就可以将视图发送到客户端。
  • res.render的第一个参数是它应该呈现的视图模板的名称。Files & Folders在这里传递没有多大意义。你需要一个名为的视图文件,我不认为你的文件名可以有空格或&符号。
  • res.render的第二个参数是您希望视图模板可以使用的变量。只使用这两个参数调用res.render会隐式地将呈现的视图发送到客户端。没有必要将回调函数作为第三个参数传递,除非您确实需要获取呈现视图的字符串版本以供在服务器上使用。
  • next是您从中间件函数调用的函数,它让express知道您已经准备好让它继续沿着中间件管道运行。这里并不需要中间件函数,但是如果需要,那么捕获的任何错误都应该作为第一个参数传递给next函数。Express知道,如果您向next传递一个值,那么它应该跳转到Express错误处理程序,并为用户呈现错误消息视图。

我相当肯定,在中间件函数或最终的请求处理函数中抛出错误仍然会被express捕获。

  • 如果函数是异步的,你就不能***永远永远***从函数返回值。这正是需要到处传递回调函数的原因。你传入一个函数,这样node就可以在你想要的数据准备好时调用它,然后node就可以调用你的回调函数并传入你想要的数据。与此同时,您的应用继续运行,并能够在等待期间处理其他代码。你可能想看看promise,因为它们清理了回调地狱,你最终在其他异步函数的回调函数中调用异步函数,创建了一个令人困惑的横向地狱金字塔,如下所示:
asyncFunction1(function (err, result) {
  if (err) return handleErr(err);
  asyncFunction2(function (err, result) {
    if (err) return handleErr(err);
    asyncFunction3(function (err, result) {
      if (err) return handleErr(err);
      asyncFunction4(function (err, result) {
        if (err) return handleErr(err);
        asyncFunction5(funciton (err, result) {
          if (err) return handleErr(err);
          // do something useful
        });
      });
    });
  });
});

Promise将使代码更具可读性。Promises也可以让你不必在 * 每个回调 * 中检查错误。查一下下面是一个使用promise的代码示例:

asyncFunction1()
  .then(function (result) {
    return asyncFunction2();
  })
  .then(function (result) {
    return asyncFunction3();
  })
  .then(function (result) {
    return asyncFunction4();
  })
  .then(function (result) {
    return asyncFunction5();
  })
  .then(function (result) {
    // do something useful
  })
  .catch(function (err) {
    // Will be called if ANY of the above generate an error.
  });

这是我现在得到的大部分反馈,可能对你来说有很多需要处理,所以我就不多说了:)

相关问题