2017-03-29 59 views
0

我写了一个函数,通过webscraping获取超链接锚点列表。Promise返回空列表

我想将所有这些锚点推到一个对象数组上,该对象数组稍后将被序列化为一个Json字符串。

Api.GetCourseSubmenuUrl方法和Api.FilterSubmenuContentList都返回承诺。

但是,下面的代码保持运行,而不会等待在.each() cheerio函数中填充数组。为什么会发生?

请注意,cheerio中的每种方法都是同步的。

我的代码使用的包:

代码:

Connection.prototype.FillCourseWithSubmenuContent = function(course){ 
    var self = this; //This class 
    var submenuItems = []; 
    return new BPromise(function(resolve, reject){ 
     return Api.GetCourseSubmenuUrl(ApiConnection.authToken).then(function(response){ 
     return request.get({url: self.url + response.url + course.id, followRedirect: false, jar: cookiejar}, function(err,httpResponse,body){ 
      if(err){ 
      reject(err); 
      } 
      var cheerio = require('cheerio'); 
      var dashboardhtml = cheerio.load(body, { 
        normalizeWhitespace: true, 
        decodeEntities: true 
       } 
     ); 
      //Find all the links on the page 
      dashboardhtml('a').each(function(i, elem) { 
       console.log("Object:"); 
       console.log({"text":dashboardhtml(elem).text(), "url":dashboardhtml(elem).attr('href')}); 
       submenuItems.push({"text":dashboardhtml(elem).text().trim(), "url":dashboardhtml(elem).attr('href')}); 
      }); 
      resolve(); 
     }); 
     }).then(function(){ 
     console.log(submenuItems); 
     return Api.FilterSubmenuContentList(ApiConnection.authToken, submenuItems); 
     }); 
    }).catch(function(error){ 
     return reject(error); 
    }); 
}; 
+0

避免['Promise'构造反模式](http://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-反模式和如何对避免-吧)! – Bergi

+0

你调用的'reject'函数甚至不在范围内。 – Bergi

+0

@Bergi我真的不知道反模式如何适合我的代码?它出错了哪里?是否在承诺中使用诺言?你在谈论第一个还是第二个拒绝? – Dragon54

回答

1

问题是通过考虑Promise constructor antipattern来解决的,由@Bergi指出。

由于请求库没有承诺支持,我仍然必须将其包装在(Bluebird)承诺中。

请注意,它也有可能是promisify库,它使生活变得更容易。但为了演示解决方案,我参加了承诺包装路线。

解决方案是:

Connection.prototype.FillCourseWithSubmenuContent = function(course){ 
    var self = this; //This class 
    var submenuItems = []; 
    return Api.GetCourseSubmenuUrl(ApiConnection.authToken).then(function(response){ 
     console.log(self.url + response.url + course.id); 
     return new BPromise(function(resolve, reject){ 
     request.get({url: self.url + response.url + course.id, followRedirect: false, jar: cookiejar}, function(err,httpResponse,body){ 
      if(err){ 
      reject(err); 
      } 
      var cheerio = require('cheerio'); 
      var dashboardhtml = cheerio.load(body, { 
        normalizeWhitespace: true, 
        decodeEntities: true 
       } 
     ); 
      //Find all the links on the page 
      dashboardhtml('a').each(function(i, elem) { 
       // console.log("Object"); 
       // console.log({"text":dashboardhtml(elem).text(), "url":dashboardhtml(elem).attr('href')}); 
       submenuItems.push({"text":dashboardhtml(elem).text().trim(), "url":dashboardhtml(elem).attr('href')}); 
      }); 
      return resolve(); 
     }); 
     }); 
    }).then(function(){ 
     console.log(submenuItems); 
     return Api.FilterSubmenuContentList(ApiConnection.authToken, submenuItems); 
    }); 
}; 
+1

+1,这就是我的意思。我甚至会去执行'resolve(body)',并将'cheerio'的东西放到一个'then'处理程序中,异常会自动被捕获 – Bergi