Что происходит при вызове методов до готовности

Внутренняя инициализация localForage построена вокруг асинхронной подготовки драйвера хранения. При создании экземпляра библиотеки происходит не мгновенное подключение к хранилищу, а последовательный процесс выбора, проверки и инициализации доступного backend’а (IndexedDB, WebSQL или localStorage). В этот промежуток объект localForage формально уже существует, но его «рабочее состояние» ещё не гарантировано.

Ключевая особенность поведения заключается в том, что библиотека принимает вызовы методов ещё до завершения подготовки драйвера. Это возможно благодаря внутренней очереди операций.

При вызове методов вроде setItem, getItem, removeItem или clear до завершения инициализации происходит следующее:

  • операция не выполняется немедленно;
  • формируется объект задачи с параметрами вызова;
  • задача помещается во внутреннюю очередь;
  • выполнение откладывается до момента готовности драйвера.

Таким образом, API остаётся синхронно-доступным с точки зрения интерфейса, но фактически работает асинхронно через буферизацию вызовов.

Состояние экземпляра до завершения инициализации

Внутреннее состояние localForage до полной готовности можно описать как «неинициализированный контекст хранения». В этот момент:

  • драйвер хранения ещё не выбран окончательно;
  • конфигурация (имя базы, storeName, driver list) может быть частично применена;
  • прямое обращение к backend API невозможно;
  • любые операции переводятся в отложенный режим.

Важно, что экземпляр не находится в ошибочном состоянии — он находится в переходном состоянии, при котором гарантируется сохранение всех вызовов.

Механизм очереди операций

Очередь представляет собой структурированный список задач, каждая из которых содержит:

  • тип операции (getItem, setItem, iterate и т.д.);
  • аргументы вызова;
  • callback или promise-резолвер;
  • контекст экземпляра.

После завершения инициализации выполняется последовательная обработка очереди в порядке добавления.

Особенность реализации заключается в том, что очередь не ограничена фиксированным размером и может накапливать значительное число операций, если инициализация задерживается (например, при выборе IndexedDB в браузерах с медленным доступом к API).

Поведение методов до ready-состояния

setItem

При вызове setItem(key, value) до готовности:

  • значение сериализуется (если необходимо);
  • операция сохраняется в очередь;
  • выполнение откладывается до инициализации драйвера;
  • после готовности выполняется запись в выбранное хранилище.

Особенность: порядок сохранения сохраняется, но фактическое время записи зависит от момента инициализации.

getItem

При вызове getItem(key) до готовности:

  • запрос также помещается в очередь;
  • результат не вычисляется заранее;
  • после готовности выполняется чтение из backend’а;
  • promise или callback разрешается после получения данных.

Важно, что до инициализации невозможно получить «мгновенный fallback» — чтение всегда откладывается.

removeItem и clear

Операции удаления ведут себя аналогично:

  • формируется задача;
  • добавляется в очередь;
  • выполняется после подключения драйвера;
  • соблюдается порядок относительно других операций.

Влияние смены драйвера на отложенные операции

Если в процессе инициализации происходит выбор другого драйвера (например, fallback с IndexedDB на localStorage), очередь не сбрасывается. Вместо этого:

  • все накопленные операции привязываются к новому backend’у;
  • пересоздаётся контекст выполнения;
  • операции исполняются уже в рамках выбранного драйвера.

Это гарантирует согласованность данных вне зависимости от того, какой storage оказался доступен.

Обработка ошибок до готовности

Если инициализация завершается с ошибкой (например, отсутствует поддерживаемый драйвер), поведение очереди меняется:

  • все отложенные операции завершаются с ошибкой;
  • промисы отклоняются с единым сообщением о невозможности инициализации;
  • callback’и получают error-аргумент.

Важно, что частично выполненных операций в этом состоянии не остаётся — либо весь набор выполняется после успешной инициализации, либо весь отклоняется.

ready-состояние как триггер выполнения очереди

После завершения процесса выбора драйвера происходит переход в состояние готовности. В этот момент:

  • очередь операций «размораживается»;
  • задачи выполняются последовательно;
  • устанавливается стабильный backend;
  • новые вызовы начинают обрабатываться напрямую без задержки.

Этот переход является ключевым моментом жизненного цикла экземпляра, поскольку именно он разделяет буферизированное и прямое выполнение.

Поведение сложных операций до готовности

iterate

При вызове iterate(callback) до инициализации:

  • операция помещается в очередь;
  • итерация выполняется только после готовности;
  • callback вызывается по каждому элементу уже из реального хранилища.

keys и length

Методы, возвращающие метаданные хранилища, также не дают промежуточных значений:

  • keys() возвращает результат только после подключения драйвера;
  • length() вычисляется на основе фактического backend’а;
  • до ready-состояния отсутствуют любые предположения о данных.

Особенности конкурентных вызовов

Если до завершения инициализации выполняется серия операций, например:

  • setItem("a", 1)
  • setItem("b", 2)
  • getItem("a")

то порядок их выполнения сохраняется строго в порядке поступления, даже если инициализация занимает значительное время. Однако результат чтения зависит от того, какой драйвер будет выбран в итоге, поскольку выполнение происходит уже после завершения инициализации.

Влияние повторной инициализации

При повторном вызове конфигурационных методов (например, смена driver или config) до завершения первого процесса:

  • предыдущая очередь может быть переинициализирована;
  • часть задач переносится в новый контекст;
  • старые операции могут быть аннулированы, если они привязаны к предыдущему состоянию.

Такой механизм предотвращает гонки между несколькими параллельными процессами инициализации.

Внутренний принцип гарантии целостности

Основной принцип работы до готовности заключается в сохранении семантики последовательного выполнения:

  • ни одна операция не теряется;
  • порядок вызовов сохраняется;
  • результат всегда соответствует состоянию после завершения инициализации;
  • API не блокирует поток выполнения JavaScript.

Эта модель позволяет использовать localForage без необходимости вручную ожидать готовности, сохраняя при этом корректность работы даже при ранних вызовах методов.