如何避免 node.js 中深度嵌套的代码?
Posted
技术标签:
【中文标题】如何避免 node.js 中深度嵌套的代码?【英文标题】:How do I avoid deeply nested code in node.js? 【发布时间】:2011-06-21 15:34:53 【问题描述】:在 node.js 中,它是事件驱动的,所有 I/O 都是通过回调完成的。所以我最终编写了如下代码:
app.get('/test', function (req, res)
http.get('some/place', function (req1, res1)
if (res1.statusCode == 200)
res1.on('data', function (data)
http.get('other/place?q=' + data, function (req2, res2)
if (res2.statusCode == 200)
res2.on('data', function (data)
db.query(data).on('data', function (rows)
res.writeHead(200)
res.end(JSON.stringify(rows))
)
)
)
)
)
)
这甚至不包括错误处理。
我能做些什么来解开这个烂摊子?
【问题讨论】:
哇!好吧,嵌套好了! 可能重复:***.com/questions/4234619/… 【参考方案1】:不要使用匿名函数。
编辑
您的代码甚至无效。您没有关闭大部分函数调用。
如果你切换到命名函数,它看起来像这样: 更新以反映关于全局命名空间的评论
(function ()
app.get('/test', f0)
function f0(req, res)
http.get('some/place', f1)
function f1(req1, res1)
if (res1.statusCode == 200)
res1.on('data', f2)
function f2(data)
http.get('other/place?q=' + data, f3)
function f3(req2, res2)
if (res2.statusCode == 200)
res2.on('data', f4)
function f4(data)
db.query(data).on('data', f5)
function f5(rows)
res.writeHead(200)
res.end(JSON.stringify(rows))
)()
【讨论】:
啊,这就是它没有正确突出显示语法的原因。固定。 @nornagon,这不会改变我的答案。 @nornagon,有一个非常简单的解决方案,我已经更新了我的示例。 此代码无效。讽刺。您不能立即调用未命名的函数声明。【参考方案2】:您可以使用async 模块来避免这种情况。
【讨论】:
【参考方案3】:我基于node-seq写了一个库,看起来是这样的:
app.get('/test', function (req, res)
Seq()
.seq(function ()
http.get('some/place', this.next)
)
.seq(function (req1, res1)
if (res1.statusCode == 200)
res1.on('data', this.next)
)
.seq(function (data)
http.get('other/place?q=' + data, this.next)
)
.seq(function (req2, res2)
if (res2.statusCode == 200)
res2.on('data', this.next)
)
.seq(function (data)
db.query(data).on('data', this.next)
)
.seq(function (rows)
res.writeHead(200)
res.end(JSON.stringify(rows))
)
)
代码是here。
此外,nodejs 邮件列表上还有一个lengthy discussion 与此问题相关。
Step 是另一个库。
【讨论】:
【参考方案4】:请看Streamline;它是一个 javascript 预处理器,可让您编写简单的“流线型”代码并将其转换为大量回调代码。
【讨论】:
【参考方案5】:清理这类事情的另一种(也许是更好的)方法是使用 EventEmitters 而不是回调。下面是一个例子,展示了几个正在使用的 EventEmitter:
var events = require('events'), 实用程序 = 需要('util'); 变种搜索=函数() “使用严格”; 变量搜索, 请求页面数据, 使返回对象, 发送结果, 空对象 = ; events.EventEmitter.call(this); 搜索 = 功能(查询) this.emit("requestPageData", query); ; requestPageData = 函数(查询) var 结果数组 = []; // 一些逻辑 如果(......某些条件......) this.emit("makeReturnObject", resultsArray); 别的 this.emit("sendResults", emptyObj); ; makeReturnObject = 函数(结果数组) var resultsObj = ; 如果(磁铁阵列) // 一些逻辑 this.emit("sendResults", resultsObj); 别的 this.emit("sendResults", emptyObj); ; 发送结果 = 函数 (obj) // 最后,用 obj 做任何你想做的事 ; this.on("requestPageData", requestPageData); this.on("makeReturnObject", makeReturnObject); this.on("sendResults", sendResults); this.search = 搜索; ; util.inherits(搜索, events.EventEmitter); module.exports = new Search();
【讨论】:
【参考方案6】:您可以使用承诺。看看这个https://github.com/kriskowal/q
【讨论】:
以上是关于如何避免 node.js 中深度嵌套的代码?的主要内容,如果未能解决你的问题,请参考以下文章
如何在没有浏览器的 node.js 中使用 FormData?
如何在单个查询中返回 node.js mysql 中的嵌套 json