事件回顾


做了一个移动端的页面,测试的时候出现了一个诡异的 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. 安卓+servlet+MySql 查询+插入(汉字乱码解决)

    问题: 安卓程序,通过servlet连接MySQL数据库,并实现查询和插入(修改,删除类似). 其中遇到的最大的问题是:汉字乱码问题(查询条件有汉字乱码.servlet的汉字到数据乱码.安卓通过ser ...

  2. SQL SERVER同步环境新增发布对象时不能生成(sp_MS+表名)同步存储过程

    在配置了同步的用户环境(订阅端:请求订阅) 在发布端: 1.企业管理器SSMS—复制—本地发布—发布属性—项目(选中发布对象) 2.在企业管理里—查看快照代理状态(启动) 在订阅服务器: USE [D ...

  3. 曲演杂坛--使用CTE时踩的小坑:No Join Predicate

    在一次系统优化中,意外发现一个比较“坑”的SQL,拿出来供大家分享. 生成演示数据: --====================================== --检查测试表是否存在 IF(O ...

  4. 设计模式C#实现(十二)——装饰模式

    意图 0 适用性 1 结构 2 实现 3 效果 4 参考 5 意图 动态的给一个对象添加一些额外的职责. 适用性 动态的为单个对象添加职责而不影响其他对象 处理那些可以撤销的职责(? 在某些功能不需要 ...

  5. subversion 1.8.5好像不是很成熟

    加:--enable-all-static1. 没找到libneon库支持,不得不用libserf。2. libserf编译要用到scons.py,所有要有python工具支持。3. 当遇到链接少ss ...

  6. Altium Desiner 警告 adding hidden net

    这是因为 一些元件 隐藏了 vcc GND 或者没有使用vcc GND ,用不着它也报警告了. 这里可以将 vcc GND删掉这个管脚.

  7. Java 工程转 C#

    一.  前言 由于要用c#写点东西,但是我不会c#啊,所以就只能先用Java写好,然后再看看 Java 和C# 的差别,再一点一点转嘛,谁知道,google一下,有软件可以直接把 Java 工程转为C ...

  8. Linux 下安装配置 JDK

    JDK 下载地址 http://www.oracle.com/technetwork/java/javase/downloads/index.html 按照自己的情况选择不同的版本下载 cd /usr ...

  9. [转]新型智慧城市总体架构 华为 新ICT 一云二网三平台

    本文转自:http://www.jpsycn.com/hangyexinwen/20160801142354.html “十三五”规划提出,充分运用现代信息技术和大数据,建设一批新型示范性智慧城市.日 ...

  10. NET Core中实现一个Token base的身份认证

    NET Core中实现一个Token base的身份认证 注:本文提到的代码示例下载地址> How to achieve a bearer token authentication and au ...