MST

星途 面试题库

面试题:网络编程中复杂异步任务的Promise解决方案 - 高级难度

在一个网络爬虫项目中,需要从多个网页获取数据,每个网页请求是一个异步操作。假设这些网页之间存在依赖关系,例如网页B的数据依赖于网页A解析出的链接,网页C的数据依赖于网页B解析出的链接,以此类推。请使用Promise设计一个解决方案来处理这种复杂的异步任务流程,并且要考虑错误处理,确保任何一个请求失败时整个流程能正确响应并记录错误信息。
35.9万 热度难度
后端开发网络编程

知识考点

AI 面试

面试题答案

一键面试
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);
    });
  1. fetchPage 函数:模拟异步的网页请求,使用 Promise 封装。通过 setTimeout 模拟网络延迟,随机生成成功或失败的结果。
  2. parsePage 函数:模拟解析页面数据获取下一个链接的操作。这里简单返回一个新的模拟链接。
  3. crawlWeb 函数:核心的爬虫控制函数。使用 Promise 管理整个异步流程。
    • currentUrl 记录当前要请求的网页链接,errorLog 用于记录所有的错误信息。
    • crawlStep 函数是递归执行的步骤,每次请求成功后解析页面获取新链接,然后继续下一个请求。如果请求失败,记录错误信息并继续尝试下一个步骤。
    • 通过 setTimeout 模拟经过一段时间认为整个流程结束,根据 errorLog 判断是否所有请求都成功,从而决定是 resolve 还是 reject 整个 Promise
  4. 调用 crawlWeb:在最后调用 crawlWeb,并通过 .then.catch 处理最终的成功或失败结果。