You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用async/await处理fetch与forEach逻辑,实现页面链接错误校验

问题原因
  • 原代码中fetch为异步网络请求,forEach遍历不会等待异步任务执行完成,fetchErrors执行结束时所有网络请求还未返回结果,所以返回的是空数组
  • 类的constructor为同步方法,原生语法不支持直接使用await调用异步逻辑
改造要点
  1. 将fetchErrors声明为async异步方法,把每个链接的检测逻辑封装为独立的Promise实例,通过Promise.all等待所有检测任务执行完成后再统一返回错误数组
  2. 调整初始化逻辑:因为constructor无法声明为async,所以异步检测逻辑通过.then回调处理返回结果,也可以单独封装init异步方法供外部调用
  3. 按照定义的ErrorObject接口规范收集错误、警告信息
完整改造后代码
interface LinkObject {
    element: HTMLAnchorElement;
    url: URL;
    checkTrigger?: HTMLButtonElement;
}

interface ErrorObject {
    element: HTMLElement;
    errors: string[];
    warnings: string[];
}


export default class LinkCheckTool {

    protected linksObjects: LinkObject[] = [];
    protected errors: ErrorObject[] = [];

    constructor() {
        // 收集页面所有a标签的逻辑保持不变
        document.querySelectorAll('a').forEach((linkElement) => {
            const button: HTMLButtonElement = document.createElement('button');
            button.classList.add('tb-o-linkobject__btn');
            const url: URL = new URL(linkElement.href);
            if (url) {
                linkElement.appendChild(button);
                this.linksObjects.push({
                    element: linkElement,
                    url: url,
                    checkTrigger: button
                })
            }
        })

        // 异步调用检测方法,所有请求完成后拿到完整错误数组
        this.fetchErrors().then(errors => {
            this.errors = errors;
            console.log(errors); // 此处可输出完整错误数组
            // 后续页面渲染结果的逻辑可以写在这里
        })
    }

    // 改造为async异步方法,返回Promise<ErrorObject[]>
    protected async fetchErrors(): Promise<ErrorObject[]> {
        // 把每个链接的检测任务封装为单独的Promise
        const checkPromises = this.linksObjects.map(async (linkObject) => {
            // 跳过javascript协议的链接
            if (linkObject.url.protocol === 'javascript:') return null;

            const errorItem: ErrorObject = {
                element: linkObject.element,
                errors: [],
                warnings: []
            }

            try {
                const response = await fetch(linkObject.url.href);
                // 检测请求是否成功
                if (!response.ok) {
                    errorItem.errors.push(`请求异常,状态码:${response.status} ${response.statusText}`);
                }
                // 可在此处扩展其他检测逻辑,比如检测重定向、响应内容异常等
            } catch (err) {
                errorItem.errors.push(`网络请求失败:${err instanceof Error ? err.message : String(err)}`);
            }

            // 仅当有错误/警告时返回该条目,否则返回null过滤
            return errorItem.errors.length || errorItem.warnings.length ? errorItem : null;
        })

        // 等待所有检测任务执行完成
        const allCheckResults = await Promise.all(checkPromises);
        // 过滤掉空结果,返回有效错误数组
        return allCheckResults.filter(Boolean) as ErrorObject[];
    }
}
补充说明
  • 如果需要检测3xx重定向错误,可以给fetch添加配置:fetch(linkObject.url.href, { redirect: 'manual' }),自行处理重定向状态判断
  • 浏览器存在同源策略限制,非同源且服务端未配置CORS允许跨域的链接,fetch请求会直接报错,属于正常的浏览器安全限制

内容的提问来源于stack exchange,提问作者Mikel Wohlschlegel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 00:36:02