一次由于开启 Safari 无痕浏览 引发的艰难“捉虫”事件
事件回顾
做了一个移动端的页面,测试的时候出现了一个诡异的 bug。别的浏览器都好好的,就 ios 的 Safari 浏览器页面停止了渲染,似乎是有一段 js 文件没有载入。但是奇怪的是,同一型号的 iphone 的 Safari 浏览器,有些可以,有些不行,一度让我以为不可能是代码的问题(如果是代码的问题,应该都挂才科学啊),而是个别机器的原因。但是最后的最后,定位出来的原因是 Safari 开启了 无痕浏览模式!
就是这样:
DEBUG
当然,除了 Safari 开启了无痕浏览外,另一个重要的原因就是程序里使用了 localStorage。localStorage 作为 H5 新兴的 API,在移动端表现良好,深受程序员青睐。但是也并不是所有移动设备都支持,所以我们一般会写成这个样子:
// 如果支持 localStorage
if (window.localStorage) {
// ...
} else {
// ...
}
但是当 Safari 开启无痕模式的时候,很显然浏览器本身是支持 localStorage 的,所以 !!window.localStorage
会返回 true,但是去使用 localStorage 的 api 的时候,就会报错(QuotaExceededError: Dom exception 22)!有没有很坑爹!明明告诉你了我特么有这个功能,召唤你来用吧来用吧,真要用了却跪舔了!所以不得不说,浏览器能力检测,1% 的情况下,也会跪啊...
再回头来看看无痕模式,顾名思义就是不记录用户浏览的数据,当 Safari 遭遇 Storage 的时候程序跪了,那么 Storage 的好兄弟 cookie 呢?用 cookie 写了一段类似的存储代码,却没有问题, nice!
既然知道了原因,那么解决方式就呼之欲出了。我们可以用 try..catch 来处理要用到 localStorage 的代码:
try {
localStorage.setItem('a', 'hello world');
console.log(localStorage.getItem('a'));
} catch(e) {
// 当 Safari 开启无痕模式时的补救措施
console.log(e.message, e.name, e.stack); // 输出错误信息
// ...
}
总结
经此一役,思考良久总结几点:
- 浏览器的功能测试并不是万能的
- 在移动端开发用到 localStorage 的时候,如果要做到完美,请考虑下用户在 Safari 下开启无痕浏览模式的情况
- 以前没觉得 try..catch 有什么用,既然知道某个代码块可能出错,为什么还要这么写呢?现在...
PS:事后发现 stackoverflow 早已有精彩解答 Iphone localStorage “QUOTA_EXCEEDED_ERR” issue
2015-12-02 更:
如果一定要适配 Safari 下的无痕浏览模式,可以在 HTML 文件最开始判断下是否处于 Safari 的无痕浏览模式中:
try {
localStorage.setItem('isPrivateMode', '1');
localStorage.removeItem('isPrivateMode');
window.isPrivateMode = false;
} catch(e) {
window.isPrivateMode = true;
}
然后再在每次调用 localStorage 的 API 的时候进行判断:
if (!window.isPrivateMode && window.localStorage) { // 不是 Safari 无痕模式并且能用 localStorage
// ...
}
2015-12-02 更:
Safari 下的无痕浏览模式似乎是忽略 localStorage 的 getItem() 和 romoveItem(),而在 setItem() 的时候报错?详见 移动端浏览器隐私模式/无痕模式使用本地存储localStorage/sessionStorage的问题。可以直接在 PC 端的 Safari 浏览器的“秘密浏览”模式下模拟(控制台输入)。
一次由于开启 Safari 无痕浏览 引发的艰难“捉虫”事件的更多相关文章
- MUI - myStorage在ios safari无痕浏览模式下的解决方案
myStorage在ios safari无痕浏览模式下的解决方案 今天看到了这个帖子LocalStorage 在 Private Browsing 下的一个限制, 吓尿了,如果用户开启了无痕浏览,ap ...
- 苹果手机Safari无痕浏览模式下系统登录成功但是页面不跳转
昨天下午,测试提了一个bug,问题是:在苹果手机Safari无痕浏览模式下系统登录成功但是页面不跳转. 思前想后找了半天没思路,后来经过同事的点拨,说可能是禁用了cookie之类的,反正我也没思路就顺 ...
- ios中safari无痕浏览模式下,localStorage的支持情况
前言 前阶段,测试提了个bug,在苹果手机中无痕模式下,搜索按钮不好使,无法跳页,同时搜索历史也没有展示(用户搜索历史时使用localStorage存储). 正文 iOS上Sarfari在无痕模式下, ...
- Safari无痕模式是不能只使用localStorage存储数据要用Cookie做补丁
safari 无痕浏览情况测试(部分手机) 1.测试机型 iPhone7 Plus 版本 11.3 iPhone6 Plus 版本 11.3.1 iPhone6 版本 10.2.1 iP ...
- 快速开启Safari的私密浏览(快捷键创建)
正常使用Safari浏览器,都会保存你的浏览记录.搜索记录,包括你的浏览习惯,经常去哪些网站等等.这样的好处是可以帮助你更快速的进入自己需要的网站,节约很多时间. 但有些情况下,你还是会偏向于选择私密 ...
- nginx开启网站目录浏览功能
一.开启全站目录浏览功能 编辑nginx.conf, 在http下面添加以下内容: autoindex on; # 开启目录文件列表 autoindex_exact_size on; # 显示出文件的 ...
- H5页面 用户启动无痕浏览本地储存 localstorage 清楚数据
移动端开发时,如果用户浏览器启用了无痕浏览,那么本地存储信息就会失效,会导致页面信息报错 解决办法: 先判断是否能适用 localStorage.setItem 如果不行在适用 cookie coo ...
- 解决Chrome Safari Opera环境下 动态创建iframe onload事件同步执行
我们先看下面的代码: setTimeout(function(){ alert(count); },2000); var count = []; document.body.appendChild(c ...
- Safari无痕模式下,storage被禁用问题
前言 Safari开启无痕模式后,localStorage和sessionStorage为空,对其进行set操作也会报错,也就是说这种情况下,storage是被禁止使用了.接下来说一下解决方法. 解决 ...
随机推荐
- vi, vim 基本使用(2)
进入vi的命令vi filename :打开或新建文件,并将光标置于第一行首vi +n filename :打开文件,并将光标置于第n行首vi + filename :打开文件,并将光标置于最后一行首 ...
- 创建android Notification
说明:根据项目选择的基础sdk,选择不同的创建Notification的方法1 在android sdk 3.0 之前直接通过 new Notification的方法直接创建通知对象 2 在andro ...
- Puppet权威指南
<Puppet权威指南>基本信息作者: 王冬生 丛书名: Linux/Unix技术丛书出版社:机械工业出版社ISBN:9787111485988上架时间:2014-12-25出版日期:20 ...
- Mina 快速入门
Mina是什么 Mina是一个基于NIO的网络框架,使用它编写程序时,可以专注于业务处理,而不用过于关心IO操作.不论应用程序采用什么协议(TCP.UDP)或者其它的,Mina提供了一套公用的接口,来 ...
- SQLServer中的死锁的介绍
简介 什么是死锁? 我认为,死锁是由于两个对象在拥有一份资源的情况下申请另一份资源,而另一份资源恰好又是这两对象正持有的,导致两对象无法完成操作,且所持资源无法释放. 什么又是阻塞? 阻塞是 ...
- JQuery 世界时间
根据表格的时间显示表格的时间,本机的时间,韩国的时间 <%@ Page Language="C#" AutoEventWireup ="true" Cod ...
- Linux 多线程编程
概念 原来指向main()的线程叫做主线程(main thread) 使用pthread_create()创建出来的线程,叫做子线程(child thread) 主/子线程只有在创建时才有区别, 创建 ...
- day 2 Linux目录结构
Linux系统的目录结构的基本介绍: 1)在逻辑上的所有目录(包括目录下的子目录)都在最高级别的目录“/”下. 根(/)目录是Linux系统中所有目录的起始点(顶点),根下面的目录及子目录是一个有层次 ...
- mysql 二进制文件增量备份
1.首先在my.cnf下添加二进制文件路径(windows下文件名称为my.ini) 在[mysqld]下添加 log-bin=mysql-bin 2.centos下默认安装mysql 5.6,数据默 ...
- Windows Azure Redis 缓存服务
8月20日,Windows Azure (中国版)开始提供Redis缓存服务,比较国际版的Microsoft Azure晚了差不多一年的时间.说实话,微软真不应该将这个重要的功能delay这么长时间, ...