关于pdf.js在IE浏览器二次刷新的报错,我有话说

首先要说的,IE浏览器简直是前端人的噩梦 ,每天一句辣鸡IE,下面我就把我大战IE三天的经历和大家一吐为快

1 梦开始

项目中要使用pdf预览功能,当时我想:这个我熟阿,pdf.js绝对是首选技术,因为它兼容IE9版本以上,Chrome等主流浏览器更是没问题。于是去pdf.js官网直接找到主流版本2.5.207下载下来,经过一把soul后,最终在Chrome浏览器和IE浏览器打开都能正常预览,心里想:这事到这就算结束了

提一嘴:为什么说2.5.207是主流版本,因为该版本对IE的兼容性很好,不少文章都提到过该版本下能完美兼容IE:例如:

vue项目使用pdfjs插件预览pdf 不兼容QQ浏览器和搜狗浏览器问题 兼容各大主流浏览器办法

pdf.js兼容ie9浏览器及以上版本

不知道怎么下载2.5.207版本的,可以到我的百度云分享下载

链接:https://pan.baidu.com/s/1zpHKqm4ZlWX5Y4QBqPPvxA?pwd=imnk

提取码:imnk

2 梦初灭

当项目上线后,IE用户发现了这么个BUG:进入预览页面偶尔能浏览正常,偶尔失败,而且失败很频繁

技术经理赶紧找到了我,让我把这个问题解决掉,相信大家都知道,这种偶然性BUG解决起来特别麻烦。

我本地项目跑起来,确实也复现了这个问题,进入页面偶尔行,偶尔不行,注意:有的版本会报undefined这个错误,有的版本会报意外地调用了方法或属性访问,如果你要问我为什么知道的,我就该上图了

pdf下载包截图.png

我把很多版本都测试了一遍,然并卵,要么就是IE不支持高版本,要么就是报那两个错误,但这两个错误其实都是同个问题导致的,这里暂且先买个关子

undefined这个错误时,总是会伴随着Unhandled promise rejection undefined的错误

抛错.png

可以看出来这是promise函数下的一个错误,但是由于IE下无法点击错误定位到相关的错误,所以你很难根据源码去找到错误的位置,这就没了思路去解决该错误

意外地调用了方法或属性访问这个错误时,能点击错误找到对应的错误位置

抛错位置.png

遇到这些错误,我们仍然习惯性的去网上找办法,看看有没有人和自己的境遇相同

抛错搜索.png

抛错搜索2.png

然而搜了大半圈,我惊奇的发现:似乎没有人和我遭遇相同,还是说我使用的姿势不对?于是我问了我另外一些做技术相关的朋友,他们也有用到pdf.js这个插件的,结果在IE也是二次刷新报错,只不过他们客户都不是IE用户,所以暂时没有发现这个问题。

既然没人解决这个问题,我就尝试自己解决。

我开始分析上面代码:第一次进入页面时,代码到这都能正常执行下去,唯有刷新页面后,代码到这里就会抛异常,当时也挺郁闷,尝试了各种try catch,debugger,发现xhr从上面创建到这的变量内容每次都是一样,于是我就郁闷了:为什么只有第一次才好使,后面就不行呢??

3 梦魇

那个时候,我开始debugger逐行分析,然而每次分析都好像徒劳,因为从上到下,从xhr创建到xhr.open,每个步骤的函数变量内容都是一样的,为什么后面就抛异常呢?我思来想去始终都没琢磨明白。

终于苦心不负有心人!在自己的坚持下,发现了规律:每次我修改代码后,ctrl+s保存代码,由于我在vue.config.js设置了hotOnly: true的热更新机制,所以都会自动重新执行一遍代码编译,而每次编译后页面都会重新刷新加载一遍,我发现IE正是在这种重新编译重新刷新页面的机制下,每次pdf预览都能正常!

这个时候我又疑惑了:为什么重新编译导致的页面刷新能够预览正常,而手动刷新页面就不好使?难道在IE浏览器中页面刷后,变量不都是重新创建、赋值的吗?还是说webpack的机制导致某些变量有缓存,而代码重新编译后才使的这些变量重新被销毁、创建?

这些都是我的猜想,然而即使这些猜想成立,我又该如何去修复?这使我到了进退两难的地步。

4 梦迹追踪

突然我灵光一闪,既然是有什么缓存机制导致的,我清除IE的本地缓存会不会好使呢?我赶紧尝试了一下,发现:天啊!果然如此,每当我清除缓存时,页面就好使了!

于是我为了证明自己的想法,满怀激动的在页面上加入上:

window.localStorage.clear();
window.sessionStorage.clear();

这时哪管的上:这么做会把所有缓存都清理了导致的后果,此时只想证明自己的想法是对的!然而现实就是给你一点糖,又恶狠狠的给你一巴掌!

缓存是都清理,但问题还在!

坚持不气馁的我,又尝试ctrl+shift+del调出IE的清缓存工具,手动清理一遍,结果噢了!!

每次我清理后,刷新页面都能正常的预览,此时IE的清理勾选项如下:

image.png

我尝试逐个勾选尝试,直到只勾选第二项:临时Internet文件和网站文件删除时,页面每次刷新都正常

222.gif

5 修梦之旅

既然知道了问题所在,咱能不能说通过代码给他解决呢?

于是我又就网上搜索相关技术

搜索3.png

还是很遗憾,没有相关的技术,我开始寻找这个临时文件的文件夹

01.png

02.png

03.png

临时文件.png

好家伙,这么多文件聚在这开party呢,仔细寻找发现有我当前页面的临时文件

image.png

我心想:把这临时文件删了会不会就妥了?事实证明我是对的,删除后刷新预览就正常!

6 终梦

问题定位到这,已经花费了两天,是时候做个了结了!

解决方法:

  • 控制项目不产生临时文件
    优点:从根源解决问题,没有临时文件,IE也不会出现这个问题

缺点:消耗资源大,由于该设置是在index.html的meta标签中设置,一旦设置所有页面都不再产生临时文件,导致每次访问都需要重新加载资源

  • 在所有的PDF预览页面的路由中新增个时间戳
    优点:操作简单

缺点:由于每次新增的时间戳都不一样,所以临时文件都会新增一个,例如我刷新四次当前PDF预览页面,就会产生四个临时文件
07.png

我的解决方案:采用第二种方法解决,第一种先暂且不说加上这个标签后,导致所有页面都不会产生临时文件,以至于每次访问每个页面都要加载过一次资源!其次这种方法还需要Nginx的配合,详细可看:

使用Cache-Control: no-store头,禁止IE浏览器保存临时文件,保护机密信息

html设置Cache-Control:no-cache/ no-store来禁止页面缓存,不起作用。

解决思路:

05.png

相关代码:

function timeStamp(url) {
    let currentTime_stamp = new Date().getTime()
    if (url.indexOf('?') > -1) {
      let start = url.indexOf('&timestamp=');
      if (start > -1) {
        url = url.substring(0, url.indexOf('&timestamp=')) + "&timestamp=" + currentTime_stamp;
      } else {
        url = url + "&timestamp=" + currentTime_stamp
      }
    } else {
      url = url + "?timestamp=" + currentTime_stamp
    }
    return url
}

window.history.pushState({}, 0, this.timeStamp(window.location.href));
  

最终经过这一番的操作下来,终于解决了。有人担心,每次刷新都会产生个临时文件,这样岂不是会占内存,其实完全可以不必担心,因为每次产生的临时文件都很小(和你代码有关),何况IE临时文件有限制文件大小的,默认是330M,满了后将不再增长。

虽然这个办法不是完美的,如果码友们有更好的建议,希望能留言交流。

最后一句:愿世界没有IE

猜你喜欢

转载自blog.csdn.net/weixin_42000816/article/details/124740828
今日推荐