我试图在每个foreach
循环后返回正在填充异步的数组。但是当我回来时,我只得到undefined
。
以下是代码块:
var navigateAndFetchPages = function (data) {
var countryPages = [];
data.forEach(function (val) {
Rq(val.esomar_url)
.then(function (data) {
var $ = cheerio.load(data),
pages_elem = $('.mt0.mb0-5.pt0').find('a').not('.active');
countryPages.push({country_name: val.country_name, links: pages_elem});
})
});
return countryPages;
};
var scraper = {
extract: function (dir) {
return landingPage(dir)
.then(function (countries) {
return navigateAndFetchPages(countries)
})
.then(function (p) {
p()
})
.catch();
}
};
答案 0 :(得分:1)
首先,请正确缩进您的代码 - 这样更容易理解!
其次,您需要接受代码的异步性。据推测,Rq
是一个异步函数:它使整个操作异步。这意味着navigateAndFetchPages
需要返回promises,而不是尝试返回数据。
执行此操作的简单方法是使用Array#map
。
var navigateAndFetchPages = function(data) {
return data.map(function(val) {
return Rq(val.esomar_url).then(function(data) {
var $ = cheerio.load(data),
pages_elem = $('.mt0.mb0-5.pt0').find('a').not('.active');
return {
country_name: val.country_name,
links: pages_elem
};
})
});
};
调用navigateAndFetchPages
的结果现在将是一系列承诺。
您可以使用Promise.all
完成所有操作:
Promise.all(navigateAndFetchPages(data)).then(function(result) {
// result is an array of objects containing your data
});
您的更新问题表明,这本身就是一系列承诺。这很容易处理:
var scraper = {
extract: function (dir) {
return landingPage(dir)
.then(function (countries) {
return Promise.all(navigateAndFetchPages(countries));
})
.then(function (p) {
p()
})
.catch();
}
};
你可以将Promise.all
放在navigateAndFetchPages
函数中,但我不会,以防您将来需要访问各个页面的数据。不过,这是你的API,所以这取决于你。
答案 1 :(得分:-1)
您可以将.map()
,Promise.all()
替换为来自.forEach()
的{{1}},return
对象,该对象将包含在.then()
链接的结果数组中到.then()
Promise.all()