2017-03-29 57 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