首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在Node.js中避免异步函数的长嵌套

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

Stack Overflow用户
提问于 2010-11-21 03:43:45
回答 22查看 62.4K关注 0票数 161

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

代码语言:javascript
复制
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();
      });
    });
  });

如果有很多这样的函数,那么嵌套就成了一个问题的

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

EN

回答 22

Stack Overflow用户

回答已采纳

发布于 2010-11-21 03:56:26

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

以下内容:

代码语言: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 ...
});

可以重写为如下所示:

代码语言:javascript
复制
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在下面的注释中指出的那样,如果您要访问内部函数中的闭包变量,上面的转换将不是一个直接的转换。在这种情况下,使用内联匿名函数甚至更可取。

票数 74
EN

Stack Overflow用户

发布于 2010-11-27 08:07:58

Kay,只需使用这些模块中的一个。

它将会变成这样:

代码语言:javascript
复制
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();
            });
        });
    });
});

如下所示:

代码语言:javascript
复制
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()
    }
);
票数 63
EN

Stack Overflow用户

发布于 2010-11-22 00:11:41

在很大程度上,我同意Daniel Vassallo的观点。如果您可以将一个复杂且嵌套很深的函数分解为单独的命名函数,那么这通常是一个好主意。如果有必要在单个函数中执行此操作,您可以使用众多可用的node.js异步库中的一个。人们已经想出了很多不同的方法来解决这个问题,所以看看node.js模块页面,看看你的想法。

为此,我自己编写了一个模块,名为async.js。使用此方法,可以将上面的示例更新为:

代码语言:javascript
复制
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();
  });
});

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

希望这对你有用!

票数 18
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4234619

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档