我正在使用node.js编写一个爬虫。首先,我需要获取主页以获取该页面上每个项目的 URL,然后我抓取每个项目的 URL 以获取它们的详细信息
fetchPage(url)
是获取链接的HTML文本
function fetchPage(url){
return new Promise(
(resolve,reject)=>{
agent
.get(url)
.end(function(err,res){
if (err){
reject(err);
} else{
resolve(res.text);
}
});
});
}
这是该爬虫的全局调用
fetchPage(link).then(
(result)=>{
const urls=getUrls(result);
for (var i=0;i<5;i++){
fetchItem(urls[i].link).then(
(result)=>{
console.log('Done');
},
(error)=>console.log(error)
);
}
},
(error)=>console.log(error)
);
在获取主页后,我处理了获取所有项目的 URL(通过 getUrls
)
fetchItem(url)
是另一个 Promise
,它确保项目的每个 HTML 文本在被 获取后都应通过
getItem
进行处理>获取页面
function fetchItem(url){
return new Promise(
(resolve,reject)=>{
fetchPage(url).then(
(result)=>{
getItem(result);
},
(error)=>reject(error)
);
});
}
它确实会爬行。它确实获得了我需要的所有元素,而且不缺少任何信息。
但是我的代码有问题。为什么控制台不为我记录 Done
消息?
结果的顺序不正确。爬取结果的顺序和我预想的不一样,和网站上的顺序不一样。
请指出我对这些异步控制有哪些误解和错误?如何保证它们的顺序呢?如何修复此代码以满足?
如果我想在完全抓取所有项目后记录消息全部完成
,确保它们完全按照正确的顺序获取,我该怎么办?
最佳答案
Done
未被调用,因为您没有解析 fetchItem
函数中创建的 Promise
。
我想为了保持结果的顺序,您可能需要使用 Promise.all 。当所有项目都被完全抓取时,它还有助于获取全部完成
消息。
我将从更改 fetchPage
函数开始,通过使用 map
将 url
转换为 fetchItem
promise 数组,我可以传递给 Promise.all
。像这样的事情
fetchPage(link).then(
(result)=>{
const urls=getUrls(result);
var promises = urls.map((url) => fetchItem(url.link));
Promise.all(promises).then((values) => {
console.log('All done');
console.log(values);
}, (error) => {
console.log(error);
});
},
(error)=>console.log(error)
);
然后将解析添加到您的 fetchItem
方法中。
function fetchItem(url){
return new Promise(
(resolve,reject)=>{
fetchPage(url).then(
(result)=>{
resolve(getItem(result));
},
(error)=>reject(error)
);
});
}
关于javascript - 如何管理多个 Promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36631083/