首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Safari不支持indexedDB.databases()

Safari不支持indexedDB.databases()
EN

Stack Overflow用户
提问于 2019-09-04 19:13:37
回答 3查看 2.5K关注 0票数 1

我使用Safari12.1,使用javascript开发IndexedDB。我需要获取所有indexedDB数据库名称,但safari不支持indexedDB.databases()函数

虽然它在chrome中得到了支持。

那么如何在Safari中获取所有的indexedDB数据库呢?

请帮帮忙。

EN

回答 3

Stack Overflow用户

发布于 2019-09-04 19:55:37

从2019年8月29日开始,safari v13.0.1看起来更好,所以请尝试Safari技术预览版。

请检查:

https://caniuse.com/#feat=indexeddb

safari

https://bugs.webkit.org

https://github.com/dfahlander/Dexie.js/issues

票数 1
EN

Stack Overflow用户

发布于 2020-09-11 02:22:40

代码语言:javascript
复制
/**
 * Polyfill for indexedDB.databases()
 * Safari and some other older browsers that support indexedDB do NOT
 * Support enumerating existing databases. This is problematic when it
 * comes time to cleanup, otherwise we could litter their device with
 * unreferenceable database handles forcing a nuclear browser clear all history.
 */

(function () {
    if (window.indexedDB && typeof window.indexedDB.databases === 'undefined') {
        const LOCALSTORAGE_CACHE_KEY = 'indexedDBDatabases';

        // Store a key value map of databases
        const getFromStorage = () =>
            JSON.parse(window.localStorage[LOCALSTORAGE_CACHE_KEY] || '{}');

        // Write the database to local storage
        const writeToStorage = value =>
            (window.localStorage[LOCALSTORAGE_CACHE_KEY] = JSON.stringify(value));

        IDBFactory.prototype.databases = () =>
            Promise.resolve(
                Object.entries(getFromStorage()).reduce((acc, [name, version]) => {
                    acc.push({ name, version });
                    return acc;
                }, [])
            );

        // Intercept the existing open handler to write our DBs names
        // and versions to localStorage
        const open = IDBFactory.prototype.open;

        IDBFactory.prototype.open = function (...args) {
            const dbName = args[0];
            const version = args[1] || 1;
            const existing = getFromStorage();
            writeToStorage({ ...existing, [dbName]: version });
            return open.apply(this, args);
        };

        // Intercept the existing deleteDatabase handler remove our
        // dbNames from localStorage
        const deleteDatabase = IDBFactory.prototype.deleteDatabase;

        IDBFactory.prototype.deleteDatabase = function (...args) {
            const dbName = args[0];
            const existing = getFromStorage();
            delete existing[dbName];
            writeToStorage(existing);
            return deleteDatabase.apply(this, args);
        };
    }
})();
票数 1
EN

Stack Overflow用户

发布于 2021-09-01 21:58:48

@jamesmfriedman的解决方案在Firefox中为我抛出了错误,当IF语句被禁用时,也会在Chrome中抛出错误。

我偶然发现了一个拦截方法调用的代理方法(来自https://javascript.plainenglish.io/javascript-how-to-intercept-function-and-method-calls-b9fd6507ff02),并将其集成到polyfill中。这段代码在2021-09-01的Chrome和Firefox中都运行得很好。

代码语言:javascript
复制
/**
 * Polyfill for indexedDB.databases()
 * Safari and some other older browsers that support indexedDB do NOT
 * Support enumerating existing databases. This is problematic when it
 * comes time to cleanup, otherwise we could litter their device with
 * unreferenceable database handles forcing a nuclear browser clear all history.
 */

// eslint-disable-next-line func-names
(function () {
  // if (window.indexedDB && typeof window.indexedDB.databases === 'undefined') {
  const LOCALSTORAGE_CACHE_KEY = 'indexedDBDatabases';

  // Helper function from plainenglish.io to use a proxy to intercept.
  // Original at https://javascript.plainenglish.io/javascript-how-to-intercept-function-and-method-calls-b9fd6507ff02
  const interceptMethodCalls = (obj, fnName, fn) => new Proxy(obj, {
    get(target, prop) {
      if (prop === fnName && typeof target[prop] === 'function') {
        return new Proxy(target[prop], {
          apply: (target2, thisArg, argumentsList) => {
            fn(prop, argumentsList);
            return Reflect.apply(target2, thisArg, argumentsList);
          },
        });
      }
      return Reflect.get(target, prop);
    },
  });

  // Store a key value map of databases
  const getFromStorage = () => JSON.parse(window.localStorage[LOCALSTORAGE_CACHE_KEY] || '{}');

  // Write the database to local storage
  const writeToStorage = (value) => {
    window.localStorage[LOCALSTORAGE_CACHE_KEY] = JSON.stringify(value);
  };

  IDBFactory.prototype.databases = () => Promise.resolve(
    Object.entries(getFromStorage()).reduce((acc, [name, version]) => {
      acc.push({ name, version });
      return acc;
    }, []),
  );

  // Intercept the existing open handler to write our DBs names
  // and versions to localStorage
  interceptMethodCalls(IDBFactory.prototype, 'open', (fnName, args) => {
    const dbName = args[0];
    const version = args[1] || 1;
    const existing = getFromStorage();
    writeToStorage({ ...existing, [dbName]: version });
  });

  // Intercept the existing deleteDatabase handler remove our
  // dbNames from localStorage
  interceptMethodCalls(IDBFactory.prototype, 'deleteDatabase', (fnName, args) => {
    const dbName = args[0];
    const existing = getFromStorage();
    delete existing[dbName];
    writeToStorage(existing);
  });

  // }
}());

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57787209

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档