如何避免Node.js中异步函数的长时间嵌套

我想创建一个页面来显示数据库中的一些数据,所以我创建了一些从我的数据库中获取数据的函数。 我只是Node.js中的一个新手,据我所知,如果我想在单个页面中使用它们(HTTP响应),我必须将它们全部嵌套在一起:

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'});
  var html = "<h1>Demo page</h1>";
  getSomeDate(client, function(someData) {
    html += "<p>"+ someData +"</p>";
    getSomeOtherDate(client, function(someOtherData) {
      html += "<p>"+ someOtherData +"</p>";
      getMoreData(client, function(moreData) {
        html += "<p>"+ moreData +"</p>";
        res.write(html);
        res.end();
      });
    });
  });

如果有这样的功能,那么嵌套就成了一个问题

有没有办法避免这种情况? 我想这与你如何组合多个异步函数有关,这似乎是一些基本的东西。


有趣的观察。 请注意,在JavaScript中,通常可以用命名函数变量替换内联匿名回调函数。

下列:

http.createServer(function (req, res) {
   // inline callback function ...

   getSomeData(client, function (someData) {
      // another inline callback function ...

      getMoreData(client, function(moreData) {
         // one more inline callback function ...
      });
   });

   // etc ...
});

可以重写成这样的样子:

var moreDataParser = function (moreData) {
   // date parsing logic
};

var someDataParser = function (someData) {
   // some data parsing logic

   getMoreData(client, moreDataParser);
};

var createServerCallback = function (req, res) {
   // create server logic

   getSomeData(client, someDataParser);

   // etc ...
};

http.createServer(createServerCallback);

但是,除非您打算在其他地方重新使用回调逻辑,否则读取内联匿名函数通常会更容易,如您的示例中所示。 它也将免除您必须为所有回调找到名称。

另外请注意,由于@pst在下面的注释中提到,如果您正在访问内部函数中的闭包变量,上述内容将不是一个简单的翻译。 在这种情况下,使用内联匿名函数更为可取。


凯,只需使用这些模块之一。

  • 流JS
  • 恐惧
  • 期货
  • 追星族
  • 节点continuables
  • 滑动
  • 节点流入
  • async.js
  • 异步
  • 它会变成这样:

    dbGet('userIdOf:bobvance', function(userId) {
        dbSet('user:' + userId + ':email', 'bobvance@potato.egg', function() {
            dbSet('user:' + userId + ':firstName', 'Bob', function() {
                dbSet('user:' + userId + ':lastName', 'Vance', function() {
                    okWeAreDone();
                });
            });
        });
    });
    

    进入这个:

    flow.exec(
        function() {
            dbGet('userIdOf:bobvance', this);
    
        },function(userId) {
            dbSet('user:' + userId + ':email', 'bobvance@potato.egg', this.MULTI());
            dbSet('user:' + userId + ':firstName', 'Bob', this.MULTI());
            dbSet('user:' + userId + ':lastName', 'Vance', this.MULTI());
    
        },function() {
            okWeAreDone()
        }
    );
    

    大多数情况下,我会同意Daniel Vassallo。 如果你可以将一个复杂的深层嵌套函数分解成单独的命名函数,那么这通常是一个好主意。 对于在单个函数中执行它的意义时,您可以使用许多node.js异步库中的一个。 人们已经想出了很多不同的方法来解决这个问题,所以看看node.js模块页面,看看你的想法。

    我为自己写了一个模块,名为async.js。 使用这个,上面的例子可以更新为:

    http.createServer(function (req, res) {
      res.writeHead(200, {'Content-Type': 'text/html'});
      async.series({
        someData: async.apply(getSomeDate, client),
        someOtherData: async.apply(getSomeOtherDate, client),
        moreData: async.apply(getMoreData, client)
      },
      function (err, results) {
        var html = "<h1>Demo page</h1>";
        html += "<p>" + results.someData + "</p>";
        html += "<p>" + results.someOtherData + "</p>";
        html += "<p>" + results.moreData + "</p>";
        res.write(html);
        res.end();
      });
    });
    

    这种方法的一个好处是,您可以快速更改代码以通过将“系列”功能更改为“并行”来并行获取数据。 更重要的是,async.js也可以在浏览器内部工作,所以你可以使用和你在node.js中一样的方法,如果你遇到任何棘手的异步代码。

    希望这很有用!

    链接地址: http://www.djcxy.com/p/79299.html

    上一篇: How to avoid long nesting of asynchronous functions in Node.js

    下一篇: What's the difference between Invoke() and BeginInvoke()