如何在我的简单快速应用程序中优化此回调层次结构?

时间:2017-06-17 13:01:27

标签: node.js express callback

我正在创建一个简单的RSS Feed聚合器。为此,我使用了一个名为“盲解析器”的模块。该模块解析rss / xml字符串并返回一个对象。

我的目标是从多个rss feed获取这些对象并渲染它们。所以我最初这样做了:

 var obj1 = {},obj2 = {}, obj3 = {};
 app.get('/',function(req,res){ 

    parser.parseURL('https://www.toptal.com/blog.rss', function (err, parsed1) {
        obj1 = parsed1;
    });              
    parser.parseURL('https://www.toptal.com/designers/blog.rss', function (err, parsed2) {
        obj2 = parsed2;
    });
    parser.parseURL('http://jsfeeds.com/feed', function (err, parsed3) {
        obj3 = parsed3;
    });
    parser.parseURL('http://www.mironov.com/feed/', function (err, parsed4) {
        obj4 = parsed4;
    });
    res.render('index', {'toptal': obj1 , 'toptaldesign' : obj2 , 'jsf': obj3 , 'product': obj4 });
});

然而它并没有像obj1一样工作,obj2,obj3和obj4结果是未定义的。 我对此并不了解。我尝试在app.get和outside之外声明变量,两者都没有效果。

所以我这样做了,

  app.get('/',function(req,res){ 

        parser.parseURL('https://www.toptal.com/blog.rss', function (err, parsed1) {
                parser.parseURL('https://www.toptal.com/designers/blog.rss', function (err, parsed2) {
                    parser.parseURL('http://jsfeeds.com/feed', function (err, parsed3) {
                        parser.parseURL('http://www.mironov.com/feed/', function (err, parsed4) {
                            res.render('index', {'toptal': parsed1 , 'toptaldesign' : parsed2 , 'rs': parsed3 , 'product': parsed4 });
                    });
                });        
            });
        });
    });

并且它有效!然而,这种方法的主要缺点是,每次我嵌套另一个rss-link时,花费的时间增加2倍。

已经加载具有三层嵌套的页面所需的时间约为20秒。

有人可以帮助我并为此提供解决方案,我也是节点的新手,所以请详细说明。

感谢。

1 个答案:

答案 0 :(得分:0)

我假设parse.parseURL函数实际上是获取指定的URL并解析其内容。您的四个parseURL请求中的每一个都是异步的,这意味着每个函数都是同步调用的,但是一旦获取了URL,它们的每个回调都会在稍后的某个时间执行。同时您的res.render调用也已经在前面的parseURL调用之后但在调用每个回调之前立即同步运行,所以在 obj1 等之前已经设置了。

当您在每个回调中嵌套调用时,如第二个示例中所示,那么您将确保在继续之前获取每个URL结果,但是当您按顺序提取每个URL时(例如,您不会获取第二个URL,直到第一个已经返回)然后执行时间会变慢。

您可以通过并行获取所有四个URL来加快速度(假设您的请求是同时处理的)。为此,如果您首先使用async之类的库,或者将代码转换为使用promises,则会更简单。如果您使用async,那么您的代码可以更改为并行获取URL,如下所示:

async.parallel([
  ( cb ) => {
    parser.parseURL('https://www.toptal.com/blog.rss', cb );
  },
  ( cb ) => {              
    parser.parseURL('https://www.toptal.com/designers/blog.rss', cb );
  },
  ( cb ) => {
    parser.parseURL('http://jsfeeds.com/feed', cb );
  },
  ( cb ) => {
    parser.parseURL('http://www.mironov.com/feed/', cb );
  }
], 
( err, results ) => {
  // Called once all requests have completed.
  res.render('index', {'toptal': results[0] , 'toptaldesign' : results[1] , 'jsf': results[2] , 'product': results[3] });
});