事件回顾


做了一个移动端的页面,测试的时候出现了一个诡异的 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. 【shell--批量远程MySQL,执行命令】-【工作总结】

    昨天下班前,老板给了一批LOG数据库IP地址,需要统计LOG表里Message字段top 10的结果,并输出到一个excel文件里.抽查看了下,有两种格式的以当天日期结尾的表名.由于数量太多,时间紧迫 ...

  2. tomcat黑/白名单设置

    vim $tomcat_home/conf/server.xml(可以单个IP或者多个ip,多个ip用|分隔,支持正则) <Context path=" reloadable=&quo ...

  3. Java设计模式 - 观察者模式

    定义 观察者模式属于对象行为型模式. 在对象之间定义一对多的依赖,这样一来当一个对象改变状态,依赖它的对象都会收到通知并自动更新. 优点 1.  主题和观察者之间抽象耦合.无论什么对象主要实现了特定的 ...

  4. 如何编译ReactNative示例程序Examples

    通过示例程序可以看到一些基本组件的使用,对于学习ReactNative是很有帮助的. 编译示例程序需要将整个项目导入到androidStudio中,androidStudio导入项目时选择react- ...

  5. <a>标签,鼠标经过或者停留触发延时响应事件

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAcUAAAEoCAIAAACmeX2PAAAgAElEQVR4nOzdd3xUdb74f3+Pu3v33t ...

  6. android 解决.XML提示ava.lang.NullPointerException at错误后XML没显示

    提示错误: java.lang.NullPointerException Exception details are logged in Window > Show View > Erro ...

  7. ES6函数剩余参数(Rest Parameters)

    我们知道JS函数内部有个arguments对象,可以拿到全部实参.现在ES6给我们带来了一个新的对象,可以拿到除开始参数外的参数,即剩余参数(废话好多 O(∩_∩)O~). 这个新的对象和argume ...

  8. Java魔法堂:找外援的利器——Runtime.exec详解

    一.前言 Java虽然五脏俱全但总有软肋,譬如获取CPU等硬件信息,当然我们可以通过JNI调用C/C++来获取,但对于对C/C++和Windows API不熟的码农是一系列复杂的学习和踩坑过程.那能不 ...

  9. hive中的一种假NULL现象

    使用hive时,我们偶尔会遇到这样的问题,当你将结果输出到屏幕时,查出的数据往往显示为null,但是当你将结果输出到文本时,却显示为空(即未填充),这是为什么呢? 在hive中有一种假NULL,它看起 ...

  10. JS MD5

    1 /* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as ...