闭包,循环和承诺

时间:2017-07-13 17:04:50

标签: javascript node.js promise closures

我已经阅读了几篇关于这个主题的帖子,但不幸的是我的情况正在挣扎。

我从一系列网址中提取一些网址,然后使用这些链接从这些网站获取(让我们说)网页标题。最后,我想要一个原始网址列表和一系列标题(来自子链接)。即,进入网站/域名,找到一些链接,卷曲这些链接以查找页面标题。

问题是我的titleArray只返回Promise而不是实际数据。我完全没有得到正确的承诺和承诺。代码按节点运行。我在我的真实代码中使用了个人网站,但是用常用网站代替了一个例子。

const popsicle = require('popsicle');

var sites = ['http://www.google.com','http://www.cnn.com'];

// loop through my sites (here I'm just using google and cnn as a test
for(var i=0;i<sites.length;i++) {
  // call function to pull subsites and get titles from them
  var titleArray = processSites(sites[i]);

  console.log(sites[i] + ": " + titleArray);
}

// get request on site and then get subsites
function processSites(url) {
  return popsicle.get(url)
    .then(function(res) {
      var data = res.body;

      // let's assume I get another collection of URLs
      // that I pull from the main site
      var subUrls = ['http://www.yahoo.com','http://www.espn.com'];
      var titleArray = [];
      for(var j=0;j<subUrls.length;i=j++) {
        var title = processSubSites(subUrls[j])
        titleArray.push(title);
      }
      return titleArray;
    });
}

function processSubSites(url) {

  return popsicle.get(url)
    .then(function(res) {
      var data = res.body;
      // let's say I pull the title of the site somehow
      var title = "The Title for " + url;
      console.log(title);
      return title;
    });

}

运行此结果后的结果是:

http://www.google.com: [object Promise]
http://www.cnn.com: [object Promise]
The Title for http://www.espn.com
The Title for http://www.espn.com
The Title for http://www.yahoo.com
The Title for http://www.yahoo.com

应该是:

http://www.google.com: ['The Title for http://www.yahoo.com', 'The Title for http://www.espn.com']
http://www.cnn.com: ['The Title for http://www.yahoo.com', 'The Title for http://www.espn.com']
...

1 个答案:

答案 0 :(得分:1)

您无法从Promise内返回正常数据。您需要返回另一个Promise以使其可链接。要在循环中处理多个Promise对象,您需要将它们推入数组并调用Promise.all(array);

const popsicle = require('popsicle');

var sites = ['http://www.google.com','http://www.cnn.com'];

var titleArrayPromises = [];
// loop through my sites (here I'm just using google and cnn as a test
for(var i=0;i<sites.length;i++) {
  titleArrayPromises.push(processSites(sites[i]));
}

var titleArray = [];
Promise.all(titleArrayPromises).then(function (titleArrays) {
  for(var i=0; i<titleArrays.length; i++) {
    titleArray.concat(titleArrays[i])
  }
  // You now have all the titles from your site list in the titleArray
})

function processSites(url) {
  return popsicle.get(url)
    .then(function(res) {
      var data = res.body;

      // let's assume I get another collection of URLs
      // that I pull from the main site
      var subUrls = ['http://www.yahoo.com','http://www.espn.com'];
      var titlePromiseArray = [];
      for(var j=0;j<subUrls.length;j++) {
        titlePromiseArray.push(processSubSites(subUrls[j]));
      }
      return Promise.all(titlePromiseArray);
    });
}

function processSubSites(url) {
  return popsicle.get(url)
    .then(function(res) {
      var data = res.body;
      // let's say I pull the title of the site somehow
      var title = "The Title for " + url;
      return Promise.resolve(title);
    });  
}