在 express get() 中正确调用下一个回调
Posted
技术标签:
【中文标题】在 express get() 中正确调用下一个回调【英文标题】:Proper calling of next callback in express get() 【发布时间】:2015-06-09 15:28:58 【问题描述】:我有一个在 nodejs 上运行的快速服务器。我有一个文件结构,我想将其转换为链接列表。我已经包含了我的递归文件结构函数。
文件结构函数
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:
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();
);
]);
但是,当我运行此程序时,我的页面显示为空白。我的jade模板渲染是这样的:
h1= title
h3= localTitle
div !result
我是否不恰当地使用了 next() 回调?为什么这不起作用?
编辑:如果您要否决我的问题,请至少提供评论并说明原因。我是 SO 新手,这样做让我很生气。
【问题讨论】:
看起来你执行callback
太快了
另外,output
在您使用 console.log 时会返回您期望的结果吗?我希望它是未定义的。
是的,输出未定义。
@KevinB 当我这样称呼它时: router.get('/', [function (req, res, next) recursiveFileTree('rootFolder'); next(); );它仍然做同样的事情。
您的递归函数几乎需要完全重写。你需要正确实现异步逻辑,fs.readdir是异步的。
【参考方案1】:
你最初做的事情有点不对劲。我重写了您的所有代码以使其更有意义。希望这会有所帮助。
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.send
、res.json
或 res.render
的处理程序)。
调用res.render
即可将视图发送给客户端。
res.render
的第一个参数是它应该呈现的视图模板的名称。 Files & Folders
在那里传递并没有多大意义。您需要一个名为该名称的视图文件,我认为您的文件名不能包含空格或 & 符号。
res.render
的第二个参数是您想让视图模板可用的变量。仅使用这两个参数调用res.render
会将渲染视图隐式发送到客户端。除非您确实需要获取渲染视图的字符串版本以在服务器上使用,否则无需传入回调函数作为第三个参数。
next
是您从中间件函数调用的函数,让 express 知道您已准备好让它继续沿中间件管道向下运行。您实际上并不需要中间件函数,但如果您这样做了,那么您捕获的任何错误都应该作为第一个参数传递给 next
函数。 Express 知道,如果您将值传递给 next
,那么它应该跳转到 express 错误处理程序并为用户呈现错误消息视图。
我相当肯定,在中间件函数或最终请求处理函数中抛出错误仍然会被 express 捕获。
如果函数是异步的,则您不能永远从函数返回值。这正是您需要在任何地方传递回调函数的原因。您正在传递一个函数,以便节点可以稍后在您想要的数据准备好时调用它,然后节点可以调用您的回调并传递您要求的数据。同时,您的应用程序继续运行并能够在等待时处理其他代码。您可能想要研究 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
);
);
);
);
);
Promises 将使该代码更具可读性。 Promise 也使您不必检查每个回调 中的错误。查找它们;)。下面是使用 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.
);
这就是我目前收到的大部分反馈,您可能需要处理很多,所以我会留在那里 :)
【讨论】:
哇,太棒了。我是否需要回调文件夹中的递归调用 += recursiveFileTree(root + '/' + file);? 我完全错过了这个花絮。我什至把它带到了我的样本中:/。这个电话肯定会使事情变得更加复杂,但它是可行的。我有几个会议,但我会在几个小时内回来更新我的答案:) 我在想“这个东西给文件夹变量返回一个值,但他只是说我永远不应该返回。”我会盯着它看,看看我能不能弄明白。非常感谢。你是回调天堂里的快递神。 另外,这应该是迭代的而不是递归的吗?我认为这可能是问题的症结所在。以上是关于在 express get() 中正确调用下一个回调的主要内容,如果未能解决你的问题,请参考以下文章
用于 $http.get() 调用的 Node Express Cross Origin
使用 express 和 node.js 重定向 301。 GET 没有被调用
如何使用Express在NodeJS中的GET请求中进行GET请求