Внутренняя инициализация localForage построена вокруг асинхронной подготовки драйвера хранения. При создании экземпляра библиотеки происходит не мгновенное подключение к хранилищу, а последовательный процесс выбора, проверки и инициализации доступного backend’а (IndexedDB, WebSQL или localStorage). В этот промежуток объект localForage формально уже существует, но его «рабочее состояние» ещё не гарантировано.
Ключевая особенность поведения заключается в том, что библиотека принимает вызовы методов ещё до завершения подготовки драйвера. Это возможно благодаря внутренней очереди операций.
При вызове методов вроде setItem, getItem,
removeItem или clear до завершения
инициализации происходит следующее:
Таким образом, API остаётся синхронно-доступным с точки зрения интерфейса, но фактически работает асинхронно через буферизацию вызовов.
Внутреннее состояние localForage до полной готовности можно описать как «неинициализированный контекст хранения». В этот момент:
Важно, что экземпляр не находится в ошибочном состоянии — он находится в переходном состоянии, при котором гарантируется сохранение всех вызовов.
Очередь представляет собой структурированный список задач, каждая из которых содержит:
getItem, setItem,
iterate и т.д.);После завершения инициализации выполняется последовательная обработка очереди в порядке добавления.
Особенность реализации заключается в том, что очередь не ограничена фиксированным размером и может накапливать значительное число операций, если инициализация задерживается (например, при выборе IndexedDB в браузерах с медленным доступом к API).
При вызове setItem(key, value) до готовности:
Особенность: порядок сохранения сохраняется, но фактическое время записи зависит от момента инициализации.
При вызове getItem(key) до готовности:
Важно, что до инициализации невозможно получить «мгновенный fallback» — чтение всегда откладывается.
Операции удаления ведут себя аналогично:
Если в процессе инициализации происходит выбор другого драйвера (например, fallback с IndexedDB на localStorage), очередь не сбрасывается. Вместо этого:
Это гарантирует согласованность данных вне зависимости от того, какой storage оказался доступен.
Если инициализация завершается с ошибкой (например, отсутствует поддерживаемый драйвер), поведение очереди меняется:
Важно, что частично выполненных операций в этом состоянии не остаётся — либо весь набор выполняется после успешной инициализации, либо весь отклоняется.
После завершения процесса выбора драйвера происходит переход в состояние готовности. В этот момент:
Этот переход является ключевым моментом жизненного цикла экземпляра, поскольку именно он разделяет буферизированное и прямое выполнение.
При вызове iterate(callback) до инициализации:
Методы, возвращающие метаданные хранилища, также не дают промежуточных значений:
keys() возвращает результат только после подключения
драйвера;length() вычисляется на основе фактического
backend’а;Если до завершения инициализации выполняется серия операций, например:
setItem("a", 1)setItem("b", 2)getItem("a")то порядок их выполнения сохраняется строго в порядке поступления, даже если инициализация занимает значительное время. Однако результат чтения зависит от того, какой драйвер будет выбран в итоге, поскольку выполнение происходит уже после завершения инициализации.
При повторном вызове конфигурационных методов (например, смена
driver или config) до завершения первого
процесса:
Такой механизм предотвращает гонки между несколькими параллельными процессами инициализации.
Основной принцип работы до готовности заключается в сохранении семантики последовательного выполнения:
Эта модель позволяет использовать localForage без необходимости вручную ожидать готовности, сохраняя при этом корректность работы даже при ранних вызовах методов.