【问题标题】:How do I avoid deeply nested code in node.js?如何避免 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))
              })
            })
          }
        })
      })
    }
  })
})

这甚至不包括错误处理。

我能做些什么来解开这个烂摊子?

【问题讨论】:

标签: node.js


【解决方案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

          【讨论】:

            猜你喜欢
            • 2013-12-01
            • 1970-01-01
            • 1970-01-01
            • 2013-05-21
            • 2015-05-07
            • 1970-01-01
            • 2017-08-17
            • 2019-02-09
            • 2022-09-28
            相关资源
            最近更新 更多