Firefox Request aborted 问题介绍

场景

针对文件下载,且下载的文件是外链的情况下,使用模拟a标签方式下载,点击的同时做接口请求操作,在火狐浏览器中会拦截接口请求,并产生request aborted报错,如下

// 创建a标签,点击进行下载
let a = document.createElement('a');
a.style = 'display: none';
a.href = url;
document.body.appendChild(a);
a.click(); 
document.body.removeChild(a);

someRequest(); // <-- 接口请求操作
# 此时在火狐浏览器中,接口报错
Uncaught (in promise) Error: Request aborted

文件外链下载方式,可查看 -> 文件外链前端下载方式

本文均在此场景下进行讨论

问题分析

尝试以下使用场景

是否报错均在火狐浏览器中,chrome中均不报错

// 1. window转跳方式
window.location.assign(url)
someRequest();
// ---- 不报错 ----


// 2.请求文件下载放在setTimeout中
setTimeout(() => {
  window.location.assign(url) 
}, 0);
someRequest();
// ---- 报错 ----


// 3.模拟点击后的操作setTimeout中
...
a.click()
...
setTimeout(() => {
  someRequest();
}, 0)
// ---- 大概率报错,也存在不报错的情况 ----


// 4.模拟点击延长setTimeout延时
...
a.click()
...
setTimeout(() => {
  someRequest();
}, 100)
// ---- 不报错 ----

网络上对于request aborted解释为通常发生在请求时,当前页面发生了转跳,部分浏览器会对于未完成的请求进行终止操作

1方式,assign转跳方式,浏览器会挂起前面执行队列,如果转跳后还在原页面(如下载操作)控制权交回浏览器,挂起任务会继续执行,所以不会有报错

对于js 创建a标签方式,代码执行到点击事件加入执行队列,请求也加入执行队列,但是UI render浏览器有充分的自主权,即浏览器可以控制页面刷新率,所以可能出现render在后几轮eventloop中

所以会出现报错情况。

为什么chrome不会产生request aborted?

初步推测浏览器click事件策略不同,chrome当前页面跳转不会对执行队列中的请求发送abort信号;有了解确切原因的朋友,请联系我

解决方案

使用4方法,确保下载后的操作是在点击下载完成之后执行

资料