如何安全可靠地检测浏览器存储是否可用?

遇到的坑

  公司H5项目中需要用到浏览器localStorage,笔者在项目中使用如下代码对localStorage的可用性进行检测:

1
2
3
if (window.localStorage) {
// TODO
}

  但是,将H5页面嵌入到公司内部通信app时,上述代码报错。出错的原因在于app内的webview会禁止localStorage的使用,就连访问window对象的localStorage属性也会报错。考虑到目前存在各种不同特性的浏览器和webview,如何才能安全可靠地检测不同浏览器环境下浏览器存储是否可用?

问题解决方案

  浏览器支持存储功能与存储功能可用不是一个概念,比如Safari在隐身模式下会将浏览器localStorage存储容量设置为0,意味着浏览器的存储功能实际不可用。对于部分浏览器而言,可以设置禁止浏览器存储。因此,笔者在项目中想通过检测window全局对象上是否有localStorage属性来判断当前浏览器localStorage是否可用的方法是非常片面的。MDN官方文档介绍了一个可以安全可靠地检测浏览器存储可用性的函数,以下函数源代码摘录自MDN文档。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function storageAvailable(type) {
try {
var storage = window[type],
x = '__storage_test__';
storage.setItem(x, x);
storage.removeItem(x);
return true;
}
catch(e) {
return e instanceof DOMException && (
// 当异常是由浏览器存储容量不够造成时,需要排除浏览器存储容量限额为0的特殊情况
// 非Firefox浏览器存储内容大小超出存储容量时所报出异常的code
e.code === 22 ||
// Firefox浏览器存储内容大小超出存储容量时所报出异常的code
e.code === 1014 ||
// 除了检测异常的code属性外,还需要检测异常的name属性,防止部分情况下异常没有code属性
// 非Firefox浏览器
e.name === 'QuotaExceededError' ||
// Firefox浏览器
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
// 排除存储容量不为0的情况
storage.length !== 0;
}
}

  上述函数对于localStorage和sessionStorage均适用,在使用浏览器存储前,利用上述函数检测浏览器存储是否可用是安全可靠的。

参考文献

  1. https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#Feature-detecting_localStorage