如何使用async/await处理fetch与forEach逻辑,实现页面链接错误校验
问题原因
- 原代码中
fetch为异步网络请求,forEach遍历不会等待异步任务执行完成,fetchErrors执行结束时所有网络请求还未返回结果,所以返回的是空数组 - 类的
constructor为同步方法,原生语法不支持直接使用await调用异步逻辑
改造要点
- 将
fetchErrors声明为async异步方法,把每个链接的检测逻辑封装为独立的Promise实例,通过Promise.all等待所有检测任务执行完成后再统一返回错误数组 - 调整初始化逻辑:因为constructor无法声明为async,所以异步检测逻辑通过
.then回调处理返回结果,也可以单独封装init异步方法供外部调用 - 按照定义的
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
相关产品推荐
相关产品推荐

