function fetchPage(url) {
return new Promise((resolve, reject) => {
// 模拟异步请求,这里用setTimeout代替真实的网络请求
setTimeout(() => {
if (Math.random() > 0.2) { // 模拟80%的成功率
resolve(`Data from ${url}`);
} else {
reject(new Error(`Failed to fetch ${url}`));
}
}, 1000);
});
}
function parsePage(data) {
// 模拟解析页面获取链接,这里简单返回下一个链接
return `new-url-${Math.random()}`;
}
function crawlWeb() {
let currentUrl = 'initial-url';
let errorLog = [];
return new Promise((resolve, reject) => {
function crawlStep() {
fetchPage(currentUrl)
.then(data => {
const newUrl = parsePage(data);
currentUrl = newUrl;
console.log(`Successfully fetched ${currentUrl}`);
crawlStep();
})
.catch(error => {
errorLog.push(error.message);
console.error(`Error in fetching ${currentUrl}:`, error);
// 如果所有页面都处理完了,就resolve
if (errorLog.length === 1) {
reject(new Error(`Overall error: ${errorLog.join(', ')}`));
} else {
crawlStep();
}
});
}
crawlStep();
// 假设经过一定步骤后认为完成了整个流程
setTimeout(() => {
if (errorLog.length === 0) {
resolve('All pages crawled successfully');
} else {
reject(new Error(`Overall error: ${errorLog.join(', ')}`));
}
}, 5000);
});
}
crawlWeb()
.then(result => {
console.log(result);
})
.catch(error => {
console.error(error);
});
fetchPage
函数:模拟异步的网页请求,使用 Promise
封装。通过 setTimeout
模拟网络延迟,随机生成成功或失败的结果。
parsePage
函数:模拟解析页面数据获取下一个链接的操作。这里简单返回一个新的模拟链接。
crawlWeb
函数:核心的爬虫控制函数。使用 Promise
管理整个异步流程。
currentUrl
记录当前要请求的网页链接,errorLog
用于记录所有的错误信息。
crawlStep
函数是递归执行的步骤,每次请求成功后解析页面获取新链接,然后继续下一个请求。如果请求失败,记录错误信息并继续尝试下一个步骤。
- 通过
setTimeout
模拟经过一段时间认为整个流程结束,根据 errorLog
判断是否所有请求都成功,从而决定是 resolve
还是 reject
整个 Promise
。
- 调用
crawlWeb
:在最后调用 crawlWeb
,并通过 .then
和 .catch
处理最终的成功或失败结果。