Internet Explorer 10: руководство для разработчиков

13 сентября 2011 г.

API индексированных баз данных (IndexedDB)

Internet Explorer 10 поддерживает API индексированных баз данных (IndexedDB), благодаря которому вы можете хранить структурированные данные. В отличие от файлов cookie и хранилища DOM, IndexedDB предоставляет возможности группировки, итерации, поиска и фильтрации объектов JavaScript.

API IndexedDB состоит из нескольких объектов, каждый из которых предназначен для определенных задач.

  • Данные хранятся в хранилищах объектов, которые являются коллекциями объектов JavaScript, чьи атрибуты содержат индивидуальные значения.
  • Каждый объект JavaScript, иногда называемый записью, в хранилище объектов имеет общий атрибут под названием путь ключа. Значение этого атрибута называется значением ключа (или просто ключом). Значения ключей являются уникальными идентификаторами записей в хранилище объектов.
  • В указателе объекты упорядочены согласно значению их общего атрибута. Указатели возвращают набор значений ключей, которые можно использовать для получения индивидуальных записей из исходного хранилища объектов.
  • Курсор представляет собой набор значений. Когда курсор определяется указателем, он представляет собой набор значений ключей, возвращенных указателем. Когда курсор определяется хранилищем объектов, он представляет собой набор сохраненных в нем записей.
  • Атрибут keyRange определяет диапазон значений указателя или набора записей в хранилище объектов. Диапазоны ключей позволяют фильтровать результаты курсора.
  • База данных содержит хранилища объектов и указатели. Базы данных также управляют транзакциями.
  • Запрос — это отдельное действие с объектом в базе данных. Например, открытие базы данных приводит к запросу объекта. Чтобы ответить на результаты запроса, необходимо определить обработчики событий.
  • Транзакция управляет контекстом операций и используется для поддержания целостности базы данных. Например, вы можете создавать хранилища объектов только в контексте транзакции смены версий. Если транзакция прервана, все операции в рамках этой транзакции отменяются.

В спецификации API индексированных баз данных определены два API: синхронный и асинхронный. Internet Explorer поддерживает асинхронный API. В результате операции с базами данных выполняются не сразу. Вместо этого операции возвращают объекты запросов, которые выполняются в фоновом режиме. Соответственно, IndexedDB — это API на основе событий. Вы можете создавать запросы и затем определять обработчики событий, отвечающие при выполнении или сбое этих запросов.

Важно. Эти возможности аналогичным образом работают в Internet Explorer 10 и приложениях Metro с использованием HTML.

Использование запросов для открытия базы данных

Поскольку разработка спецификации API индексированных баз данных еще не завершена, для свойства msIndexedDB в Internet Explorer используется префикс поставщика. Чтобы получить наилучший результат, используйте распознавание возможностей для доступа к API IndexedDB, как показано в следующем примере.

var ixDB;
if ( window.indexedDB ) {
   ixDB = window.indexedDB;
} else if ( window.msIndexedDB ) {
   ixDB = window.msIndexedDB;

Когда вы открываете базу данных, возвращается объект IDBRequest. Однако это не означает, что запрос уже обработан. Этот объект используется для отслеживания результатов запроса, которые станут известны после завершения обработки запроса в фоновом режиме. Используйте этот объект для определения обработчиков событий, которые отреагируют на результаты запроса, как показано в примере ниже.

var dbReq = ixDB.open( "Database1" );
dbReq.onsuccess = function( evt ) {
  oDB = evt.target.result;
};

Объекты запросов поддерживают такие события, как onsuccess и onerror. В предыдущем примере встроенная функция присваивает результаты запроса глобальной переменной, которая поддерживает подключение к отрытой базе данных. Результат изменяется в зависимости от запроса.

Объекты запросов выполняются, когда они выходят за пределы области, то есть когда заканчивается текущий блок JavaScript.

Создание транзакций

Все операции с IndexedDB производятся в рамках транзакции. Это позволяет обеспечить целостность действий базы данных при работе с разнообразными запросами, в частности с запросами, отправленными из отдельных окон или рабочих потоков. Если транзакция завершается нормально, изменения, выполненные во время транзакции, автоматически фиксируются (сохраняются). Если транзакция прерывается, все изменения откатываются (отменяются).

Интерфейс IndexedDB предусматривает три типа транзакций:

READ_ONLY Разрешает операции, которые не изменяют данные.
READ_WRITE Разрешает чтение и изменение данных. Блокирует другие транзакции READ_WRITE и VERSION_CHANGE.
VERSION_CHANGE Разрешает все операции, но блокирует все остальные транзакции. Хранилища объектов и указатели можно создавать только в случае, когда такая транзакция является активной.


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

  var oTx = db.transaction( "Objectstore1", IDBTransaction.READ_ONLY);
  oTx.oncomplete = handleTransactionComplete;
  oTx.onabort = handleTransactionAbort;
  oTx.onerror = handleTransactionError;  try {
    var objStore = otx.objectStore("ObjectStore1");   
    var req = objStore.get("AKeyValue");
    req.onsuccess = function( evt ) {
       doSomethingWithValue( evt.target.result );
    }
    req.onerror = handleRequestFailure;
  }
  catch (ex) {
    handleException( ex );
}

Транзакции могут также ограничивать доступ к хранилищам объектов в пределах своего действия. Например, транзакция READ_WRITE предотвращает выполнение транзакций VERSION_CHANGE. Таким образом, следует использовать транзакции, соответствующие вашим задачам. Например, транзакции READ_ONLY позволяют считывать данные из хранилищ объектов.

Транзакции VERSION_CHANGE позволяют создавать (или удалять) хранилища объектов и указатели, а также инициализируются с помощью метода setVersion, как показано в следующем примере.

// In this example, showResults() is a function that displays messages to the user.
if ( oDB == null ) {
   showResults( "Can't update version; the database is not open." );
} else {
  var dbReq = oDB.setVersion( "1.0" );
  dbReq.onsuccess = createSchema;
  dbReq.onerror = function( evt ) {
     showResults ( "The transaction encountered an error: " +
                    evt.message );
  }
  dbReq.onabort = function( evt ) {
    showResults ( "The transaction was canceled." );
  }
  }
}
function createSchema(evt)
{
   var oTx = evt.target.result;
   oTx.oncomplete = function( evt ) {
      showResults( "Transaction complete." );
   }
   oTx.onabort = function( evt ) {
      showResults( "Transaction canceled." );
   }
   oTx.onerror = function( evt ) {
      showResults( "Transaction error: " + evt.message + "." );
   }
   var oObjStore = oDB.createObjectStore( "ObjectStore1" );
}

В этом примере событие onsuccess запроса setVersion вызывает функцию, которая создает хранилища объектов и указатели.

Выполнение стандартных задач

В этом разделе описано, как выполнять распространенные операции с базами данных.

  • Для добавления объектов в хранилище объектов откройте его и вызовите метод add.
  • Для обновления объекта «record» в хранилище объектов используйте метод put, применив значение ключа записи, которую вы хотите заменить. Обратите внимание, что если такое значение ключа все еще отсутствует в хранилище объектов, будет добавлена новая запись.
  • Чтобы обновить объект «record» в курсоре, используйте метод курсора update (обратите внимание, что если исходная запись ранее была удалена, этот метод создаст новую запись).
  • Получить доступ к отдельным записям в хранилище объектов можно следующими методами:
    • Для возвращения в хранилище объектов отдельной записи откройте хранилище объектов и используйте метод get, чтобы вернуть объект, соответствующий значению ключа.
    • Для возвращения в хранилище объектов набора записей откройте хранилище объектов и используйте метод openCursor, чтобы получить курсор, который позволит вам провести итерацию каждой записи.
  • Для фильтрации записей в хранилище объектов используйте диапазон ключа. Этот диапазон возвращает курсор, с которым вы можете провести итерацию. Если вы хотите, чтобы этот курсор представлял записи в другом порядке, например в нисходящем, или сортировал их по значению общего атрибута, передайте диапазон ключа как параметр методу указателя openCursor. Вы также можете:
    • Определить диапазон ключа, открыть хранилище объектов и затем использовать диапазон ключа как параметр для метода «openCursor» хранилища объектов.
    • Открыть хранилище объектов, определить новый или открыть существующий указатель хранилища объектов, после чего вызвать метод «openCursor» для указателя (обратите внимание, что вы также можете передать диапазон ключа как необязательный параметр методу «openCursor»).
  • Используйте метод delete для удаления отдельных записей из хранилища объектов или курсора. Используйте метод clear для удаления всех записей из хранилища объектов.
  • Дополнительные сведения и примеры см. на сайте Internet Explorer Test Drive.