事件回顾


做了一个移动端的页面,测试的时候出现了一个诡异的 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);  // 输出错误信息

  // ...
}

总结


经此一役,思考良久总结几点:

  1. 浏览器的功能测试并不是万能的
  2. 在移动端开发用到 localStorage 的时候,如果要做到完美,请考虑下用户在 Safari 下开启无痕浏览模式的情况
  3. 以前没觉得 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 无痕浏览 引发的艰难“捉虫”事件的更多相关文章

  1. MUI - myStorage在ios safari无痕浏览模式下的解决方案

    myStorage在ios safari无痕浏览模式下的解决方案 今天看到了这个帖子LocalStorage 在 Private Browsing 下的一个限制, 吓尿了,如果用户开启了无痕浏览,ap ...

  2. 苹果手机Safari无痕浏览模式下系统登录成功但是页面不跳转

    昨天下午,测试提了一个bug,问题是:在苹果手机Safari无痕浏览模式下系统登录成功但是页面不跳转. 思前想后找了半天没思路,后来经过同事的点拨,说可能是禁用了cookie之类的,反正我也没思路就顺 ...

  3. ios中safari无痕浏览模式下,localStorage的支持情况

    前言 前阶段,测试提了个bug,在苹果手机中无痕模式下,搜索按钮不好使,无法跳页,同时搜索历史也没有展示(用户搜索历史时使用localStorage存储). 正文 iOS上Sarfari在无痕模式下, ...

  4. Safari无痕模式是不能只使用localStorage存储数据要用Cookie做补丁

    safari 无痕浏览情况测试(部分手机)   1.测试机型 iPhone7 Plus  版本 11.3 iPhone6 Plus  版本 11.3.1 iPhone6    版本 10.2.1 iP ...

  5. 快速开启Safari的私密浏览(快捷键创建)

    正常使用Safari浏览器,都会保存你的浏览记录.搜索记录,包括你的浏览习惯,经常去哪些网站等等.这样的好处是可以帮助你更快速的进入自己需要的网站,节约很多时间. 但有些情况下,你还是会偏向于选择私密 ...

  6. nginx开启网站目录浏览功能

    一.开启全站目录浏览功能 编辑nginx.conf, 在http下面添加以下内容: autoindex on; # 开启目录文件列表 autoindex_exact_size on; # 显示出文件的 ...

  7. H5页面 用户启动无痕浏览本地储存 localstorage 清楚数据

    移动端开发时,如果用户浏览器启用了无痕浏览,那么本地存储信息就会失效,会导致页面信息报错 解决办法: 先判断是否能适用 localStorage.setItem 如果不行在适用  cookie coo ...

  8. 解决Chrome Safari Opera环境下 动态创建iframe onload事件同步执行

    我们先看下面的代码: setTimeout(function(){ alert(count); },2000); var count = []; document.body.appendChild(c ...

  9. Safari无痕模式下,storage被禁用问题

    前言 Safari开启无痕模式后,localStorage和sessionStorage为空,对其进行set操作也会报错,也就是说这种情况下,storage是被禁止使用了.接下来说一下解决方法. 解决 ...

随机推荐

  1. oracle 分析函数的使用(1)

    LISTAGG(columnName,'拼接符') WITHIN GROUP(ORDER BY clause) --order by 子句决定拼接内容的顺序 LISTAGG(columnName,'' ...

  2. go sync.Mutex 设计思想与演化过程 (一)

    go语言在云计算时代将会如日中天,还抱着.NET不放的人将会被淘汰.学习go语言和.NET完全不一样,它有非常简单的runtime 和 类库.最好的办法就是将整个源代码读一遍,这是我见过最简洁的系统类 ...

  3. Oracle global database name与db link的纠缠关系

    ORACLE数据库中Global Database Name与DB LINKS的关系还真是有点纠缠不清,在说清楚这个关系前,我们先来了解一下Global Database Name的概念 Global ...

  4. win8.1 user profile service 服务登录失败

    在Win 8.1 上新建个用户后,不能登录. 出现 user profile service 服务登录失败. 无法加载用户配置文件. 网上大部分相同提示的问题是有关已有账号不能再次登陆的. 解决方式是 ...

  5. 烂泥:【解决】VMware Workstation中安装ESXI5.0双网卡问题

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 由于需要做ESXI相关的实验,所以就在自己的机器上利用VM虚拟ESXI进行实验.因为此次实验是需要两块网卡的,所以就在创建ESXI虚拟机时添加了两块网卡 ...

  6. 修改/etc/profile文件

    通常情况下,/etc/profile文件是只读的,直接用vi或gedit打开修改后是无法保存的.要修改profile,需要取得root权限,(使用gedit编辑)应该如下: $sudo gedit / ...

  7. (二)cordova+framework7入门——笑笑APP

    [前言] framework7确实做的很赞,但是一直各种原因没有做什么app, 这个感觉就像大厨遇到百年难见的好材料,不炒个菜憋的慌, 机缘巧合周一周二两个晚上做了一个简单app,先看下效果: ios ...

  8. c++实现矩阵类矩阵行列式,伴随矩阵,逆矩阵

    //Matrix ver1.0 //只支持矩阵内部(方阵)的运算 #include<iostream> #include<math.h> using namespace std ...

  9. bzoj-4517 4517: [Sdoi2016]排列计数(组合数学)

    题目链接: 4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 846  Solved: 530[Submit][ ...

  10. POJ 3608 Bridge Across Islands --凸包间距离,旋转卡壳

    题意: 给你两个凸包,求其最短距离. 解法: POJ 我真的是弄不懂了,也不说一声点就是按顺时针给出的,不用调整点顺序. 还是说数据水了,没出乱给点或给逆时针点的数据呢..我直接默认顺时针给的点居然A ...