我的webapp在IOS的JavaScript错误Safari浏览器的隐私浏览:
JavaScript的:错误
未定义
QUOTA_EXCEEDED_ERR:DOM异常22:试图添加一些存储...
我的代码:
localStorage.setItem('test',1)
我的webapp在IOS的JavaScript错误Safari浏览器的隐私浏览:
JavaScript的:错误
未定义
QUOTA_EXCEEDED_ERR:DOM异常22:试图添加一些存储...
我的代码:
localStorage.setItem('test',1)
显然,这是由设计。 当Safari浏览器(OS X或iOS)在私人浏览模式,它看起来好像localStorage
是可用的,但试图调用setItem
抛出异常。
store.js line 73
"QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage that exceeded the quota."
什么情况是,window对象仍然暴露出localStorage
全局命名空间,但是当你调用setItem
,这将引发异常。 任何呼叫removeItem
被忽略。
我相信,简单的解决办法(虽然我没有测试过这个跨浏览器还)会改变函数isLocalStorageNameSupported()
测试,你还可以设置一些价值。
https://github.com/marcuswestin/store.js/issues/42
function isLocalStorageNameSupported()
{
var testKey = 'test', storage = window.sessionStorage;
try
{
storage.setItem(testKey, '1');
storage.removeItem(testKey);
return localStorageName in win && win[localStorageName];
}
catch (error)
{
return false;
}
}
贴在上面的链接的修复并没有为我工作。 该做的:
function isLocalStorageNameSupported() {
var testKey = 'test', storage = window.localStorage;
try {
storage.setItem(testKey, '1');
storage.removeItem(testKey);
return true;
} catch (error) {
return false;
}
}
源自http://m.cg/post/13095478393/detect-private-browsing-mode-in-mobile-safari-on-ios5
正如在其他的答案中提到,您总能获得的QuotaExceededError在iOS和OS X的Safari浏览器专用模式时localStorage.setItem
(或sessionStorage.setItem
)被调用。
一个解决办法是做一个try / catch或Modernizr的检查中使用的每个实例setItem
。
但是,如果你想有一个垫片,它只是全球停止这种错误被抛出,以防止你的JavaScript的其余部分断裂,您可以使用此:
https://gist.github.com/philfreo/68ea3cd980d72383c951
// Safari, in Private Browsing Mode, looks like it supports localStorage but all calls to setItem
// throw QuotaExceededError. We're going to detect this and just silently drop any calls to setItem
// to avoid the entire page breaking, without having to do a check at each usage of Storage.
if (typeof localStorage === 'object') {
try {
localStorage.setItem('localStorage', 1);
localStorage.removeItem('localStorage');
} catch (e) {
Storage.prototype._setItem = Storage.prototype.setItem;
Storage.prototype.setItem = function() {};
alert('Your web browser does not support storing settings locally. In Safari, the most common cause of this is using "Private Browsing Mode". Some settings may not save or some features may not work properly for you.');
}
}
在我的背景下,刚刚发展起来的一类抽象。 当我的应用程序启动时,我检查localStorage的是通过调用getStorage工作()。 这个功能也返回:
在我的代码,我从来没有直接调用的localStorage。 我叫cusSto全局变量,我不得不通过调用初始化getStorage()。
这样一来,它的工作原理与私人浏览或特定版本的Safari
function getStorage() {
var storageImpl;
try {
localStorage.setItem("storage", "");
localStorage.removeItem("storage");
storageImpl = localStorage;
}
catch (err) {
storageImpl = new LocalStorageAlternative();
}
return storageImpl;
}
function LocalStorageAlternative() {
var structureLocalStorage = {};
this.setItem = function (key, value) {
structureLocalStorage[key] = value;
}
this.getItem = function (key) {
if(typeof structureLocalStorage[key] != 'undefined' ) {
return structureLocalStorage[key];
}
else {
return null;
}
}
this.removeItem = function (key) {
structureLocalStorage[key] = undefined;
}
}
cusSto = getStorage();
为了扩大在别人的答案,这里是一个紧凑的解决方案,不公开/添加任何新的变数。 它不包括所有基地,但它应该适应谁只是想要一个单页的应用程序保持功能(尽管重装后没有任何数据持久性)最多的人。
(function(){
try {
localStorage.setItem('_storage_test', 'test');
localStorage.removeItem('_storage_test');
} catch (exc){
var tmp_storage = {};
var p = '__unique__'; // Prefix all keys to avoid matching built-ins
Storage.prototype.setItem = function(k, v){
tmp_storage[p + k] = v;
};
Storage.prototype.getItem = function(k){
return tmp_storage[p + k] === undefined ? null : tmp_storage[p + k];
};
Storage.prototype.removeItem = function(k){
delete tmp_storage[p + k];
};
Storage.prototype.clear = function(){
tmp_storage = {};
};
}
})();
我不得不使用离子框架(角+科尔多瓦)同样的问题。 我知道这不是解决问题,但它是一个基于以上问题的答案对角应用程序的代码。 您将有localStorage的Safari上的IOS版本一个临时解决方案。
下面是代码:
angular.module('myApp.factories', [])
.factory('$fakeStorage', [
function(){
function FakeStorage() {};
FakeStorage.prototype.setItem = function (key, value) {
this[key] = value;
};
FakeStorage.prototype.getItem = function (key) {
return typeof this[key] == 'undefined' ? null : this[key];
}
FakeStorage.prototype.removeItem = function (key) {
this[key] = undefined;
};
FakeStorage.prototype.clear = function(){
for (var key in this) {
if( this.hasOwnProperty(key) )
{
this.removeItem(key);
}
}
};
FakeStorage.prototype.key = function(index){
return Object.keys(this)[index];
};
return new FakeStorage();
}
])
.factory('$localstorage', [
'$window', '$fakeStorage',
function($window, $fakeStorage) {
function isStorageSupported(storageName)
{
var testKey = 'test',
storage = $window[storageName];
try
{
storage.setItem(testKey, '1');
storage.removeItem(testKey);
return true;
}
catch (error)
{
return false;
}
}
var storage = isStorageSupported('localStorage') ? $window.localStorage : $fakeStorage;
return {
set: function(key, value) {
storage.setItem(key, value);
},
get: function(key, defaultValue) {
return storage.getItem(key) || defaultValue;
},
setObject: function(key, value) {
storage.setItem(key, JSON.stringify(value));
},
getObject: function(key) {
return JSON.parse(storage.getItem(key) || '{}');
},
remove: function(key){
storage.removeItem(key);
},
clear: function() {
storage.clear();
},
key: function(index){
storage.key(index);
}
}
}
]);
来源: https://gist.github.com/jorgecasar/61fda6590dc2bb17e871
享受你的编码!
下面是使用AngularJS解决IIFE和利用的事实, 服务是单身 。
这导致isLocalStorageAvailable
立即被设置在该服务首先注射,并避免不必要的运行检查每次本地存储需要被访问。
angular.module('app.auth.services', []).service('Session', ['$log', '$window',
function Session($log, $window) {
var isLocalStorageAvailable = (function() {
try {
$window.localStorage.world = 'hello';
delete $window.localStorage.world;
return true;
} catch (ex) {
return false;
}
})();
this.store = function(key, value) {
if (isLocalStorageAvailable) {
$window.localStorage[key] = value;
} else {
$log.warn('Local Storage is not available');
}
};
}
]);
看来,Safari浏览器11改变的行为,并在私人浏览器窗口现在本地存储的作品。 万岁!
我们所使用的Safari隐私浏览失败的Web应用程序,现在完美的作品。 它总是在Chrome的隐私浏览模式,这一直允许写入到本地存储工作的罚款。
这是记录在苹果的Safari浏览器技术预览版本的笔记 -和WebKit的发行说明 -发布29,这是2017年5月。
特别:
我刚刚创建的这个回购协议提供sessionStorage
与localStorage
功能,不支持的或禁用浏览器。
支持的浏览器
这个怎么运作
它可以检测与存储类型的功能。
function(type) {
var testKey = '__isSupported',
storage = window[type];
try {
storage.setItem(testKey, '1');
storage.removeItem(testKey);
return true;
} catch (error) {
return false;
}
};
设置StorageService.localStorage
到window.localStorage
如果支持,或创建一个cookie存储。 设置StorageService.sessionStorage
到window.sessionStorage
如果支持或存储器的SPA,饼干存储与使sesion功能的非SPA创建。
在ES6共享完整地阅读与支持支票写localStorage的实例
const LOCAL_STORAGE_KEY = 'tds_app_localdata';
const isSupported = () => {
try {
localStorage.setItem('supported', '1');
localStorage.removeItem('supported');
return true;
} catch (error) {
return false;
}
};
const writeToLocalStorage =
components =>
(isSupported ?
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(components))
: components);
const isEmpty = component => (!component || Object.keys(component).length === 0);
const readFromLocalStorage =
() => (isSupported ? JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY)) || {} : null);
这将确保您的按键设置,并在所有浏览器中正确检索。
下面是一个Angular2 +服务版本的内存存储选择,你可以注入到你的组件的基础上,皮埃尔·勒鲁的回答。
import { Injectable } from '@angular/core';
// Alternative to localstorage, memory
// storage for certain browsers in private mode
export class LocalStorageAlternative {
private structureLocalStorage = {};
setItem(key: string, value: string): void {
this.structureLocalStorage[key] = value;
}
getItem(key: string): string {
if (typeof this.structureLocalStorage[key] !== 'undefined' ) {
return this.structureLocalStorage[key];
}
return null;
}
removeItem(key: string): void {
this.structureLocalStorage[key] = undefined;
}
}
@Injectable()
export class StorageService {
private storageEngine;
constructor() {
try {
localStorage.setItem('storage_test', '');
localStorage.removeItem('storage_test');
this.storageEngine = localStorage;
} catch (err) {
this.storageEngine = new LocalStorageAlternative();
}
}
setItem(key: string, value: string): void {
this.storageEngine.setItem(key, value);
}
getItem(key: string): string {
return this.storageEngine.getItem(key);
}
removeItem(key: string): void {
this.storageEngine.removeItem(key);
}
}
var mod = 'test';
try {
sessionStorage.setItem(mod, mod);
sessionStorage.removeItem(mod);
return true;
} catch (e) {
return false;
}
下面的脚本解决我的问题:
// Fake localStorage implementation.
// Mimics localStorage, including events.
// It will work just like localStorage, except for the persistant storage part.
var fakeLocalStorage = function() {
var fakeLocalStorage = {};
var storage;
// If Storage exists we modify it to write to our fakeLocalStorage object instead.
// If Storage does not exist we create an empty object.
if (window.Storage && window.localStorage) {
storage = window.Storage.prototype;
} else {
// We don't bother implementing a fake Storage object
window.localStorage = {};
storage = window.localStorage;
}
// For older IE
if (!window.location.origin) {
window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
}
var dispatchStorageEvent = function(key, newValue) {
var oldValue = (key == null) ? null : storage.getItem(key); // `==` to match both null and undefined
var url = location.href.substr(location.origin.length);
var storageEvent = document.createEvent('StorageEvent'); // For IE, http://stackoverflow.com/a/25514935/1214183
storageEvent.initStorageEvent('storage', false, false, key, oldValue, newValue, url, null);
window.dispatchEvent(storageEvent);
};
storage.key = function(i) {
var key = Object.keys(fakeLocalStorage)[i];
return typeof key === 'string' ? key : null;
};
storage.getItem = function(key) {
return typeof fakeLocalStorage[key] === 'string' ? fakeLocalStorage[key] : null;
};
storage.setItem = function(key, value) {
dispatchStorageEvent(key, value);
fakeLocalStorage[key] = String(value);
};
storage.removeItem = function(key) {
dispatchStorageEvent(key, null);
delete fakeLocalStorage[key];
};
storage.clear = function() {
dispatchStorageEvent(null, null);
fakeLocalStorage = {};
};
};
// Example of how to use it
if (typeof window.localStorage === 'object') {
// Safari will throw a fit if we try to use localStorage.setItem in private browsing mode.
try {
localStorage.setItem('localStorageTest', 1);
localStorage.removeItem('localStorageTest');
} catch (e) {
fakeLocalStorage();
}
} else {
// Use fake localStorage for any browser that does not support it.
fakeLocalStorage();
}
它检查是否存在的localStorage,可以使用和否定的情况下,它会创建一个假的本地存储,并使用它,而不是原来的localStorage的。 请让我知道如果你需要更多的信息。