Метод defineDriver служит механизмом расширения системы
хранения, позволяя подключать собственные драйверы, совместимые с
внутренним контрактом библиотеки. Через него формируется слой абстракции
над различными механизмами хранения данных (IndexedDB, WebSQL,
localStorage), а также реализуются пользовательские адаптеры с
произвольной логикой.
defineDriver(driverObject: Object, callback?: Function): Promise<void>
Метод возвращает Promise, который резолвится после
успешной регистрации драйвера. Второй аргумент — необязательный
callback, используемый в старом стиле асинхронного API.
defineDriver выполняет регистрацию объекта-драйвера в
глобальном реестре доступных хранилищ. После регистрации драйвер
становится доступным для использования через setDriver.
Внутренне происходит:
_support или supports).Объект, передаваемый в defineDriver, должен
соответствовать контракту драйвера. Он описывает набор обязательных и
дополнительных методов, обеспечивающих CRUD-операции и управление
состоянием хранилища.
_driverУникальный строковый идентификатор драйвера.
_driver: 'customDriverName'
Используется системой для регистрации и выбора драйвера.
_initStorageМетод инициализации хранилища. Вызывается при активации драйвера
через setDriver.
_initStorage(options): Promise<void>
Задачи:
getItemgetItem(key): Promise<any>
Возвращает значение по ключу. При отсутствии данных возвращается
null.
setItemsetItem(key, value): Promise<any>
Сохраняет значение по ключу и возвращает сохранённое значение.
removeItemremoveItem(key): Promise<void>
Удаляет запись по ключу.
clearclear(): Promise<void>
Полная очистка хранилища драйвера.
lengthlength(): Promise<number>
Возвращает количество записей в хранилище.
keykey(index): Promise<string | null>
Возвращает ключ по индексу.
iterateiterate(iteratorFunction, callback?): Promise<any>
Итерация по всем ключам и значениям хранилища.
В терминах расширенного описания интерфейса:
interface Driver {
_driver: string;
_initStorage: (options?: any) => Promise<void>;
getItem: (key: string) => Promise<any>;
setItem: (key: string, value: any) => Promise<any>;
removeItem: (key: string) => Promise<void>;
clear: () => Promise<void>;
length: () => Promise<number>;
key: (index: number) => Promise<string | null>;
iterate: (
iterator: (value: any, key: string, iterationNumber: number) => any,
callback?: Function
) => Promise<any>;
_support?: boolean | (() => boolean);
}
defineDriverФактическое определение метода:
defineDriver(
driver: Driver,
callback?: (error?: Error) => void
): Promise<void>
После вызова defineDriver выполняется последовательность
шагов:
Проверяется наличие обязательных методов и идентификатора
_driver. При отсутствии критических полей регистрация
прерывается.
Методы драйвера оборачиваются в промисы, если возвращают значения в синхронном виде. Это обеспечивает единый асинхронный контракт.
Драйвер добавляется в внутренний массив доступных стратегий хранения.
Если передан callback, он вызывается после завершения регистрации:
callback(error)
При успешной регистрации error равен
undefined.
Основной результат метода возвращается через
Promise.resolve() после завершения всех шагов.
Все операции приводятся к асинхронной форме, даже если исходный
механизм хранения синхронный (например, localStorage). Это
обеспечивает единообразное API.
Каждый драйвер работает в изолированном контексте. Состояние не разделяется между драйверами, даже если они используют один и тот же backend.
setDriverПосле регистрации драйвера через defineDriver он
становится доступным для выбора:
setDriver('customDriverName')
Ошибки регистрации обрабатываются следующим образом:
_driver приводит к немедленному отклонению
Promise;_initStorage прерывают процесс
активации._supportПоле _support позволяет определить доступность драйвера
в текущей среде.
Возможные формы:
_support: true
или
_support: () => {
return typeof indexedDB !== 'undefined';
}
Если функция возвращает false, драйвер исключается из
выбора при автоматическом определении.
const customDriver = {
_driver: 'custom-driver',
_initStorage: async function () {
this._db = new Map();
},
getItem: async function (key) {
return this._db.get(key) || null;
},
setItem: async function (key, value) {
this._db.set(key, value);
return value;
},
removeItem: async function (key) {
this._db.delete(key);
},
clear: async function () {
this._db.clear();
},
length: async function () {
return this._db.size;
},
key: async function (index) {
return Array.from(this._db.keys())[index] || null;
},
iterate: async function (fn) {
let i = 0;
for (const [key, value] of this._db.entries()) {
fn(value, key, i++);
}
}
};
defineDriverdefineDriver(customDriver)
.then(() => console.log('registered'));
или
defineDriver(customDriver, (err) => {
if (err) {
console.error(err);
}
});
После регистрации драйвер становится частью глобального списка
доступных хранилищ. При вызове setDriver происходит выбор
наиболее подходящего драйвера из этого списка или прямое назначение по
имени _driver.
Любой драйвер, зарегистрированный через defineDriver,
обязан сохранять следующие свойства:
defineDriver(driver: Driver, callback?: Function): Promise<void>
где Driver представляет строго определённый интерфейс с
набором обязательных методов и идентификатором _driver,
обеспечивающим интеграцию с системой хранилищ localForage.