JavaScript. Подробное руководство, 6-е издание, стр. 397

Пример 22.14. Синхронный прикладной интерфейс для работы с файловой системой

<b>// Утилиты для работы с файловой системой, использующие синхронный прикладной</b>

<b>// интерфейс, предназначенный для фоновых потоков выполнения</b>

<b>var filesystem = requestFileSystemSync(PERSISTENT, 10*1024*1024);</b>

<b>function readTextFile(name) {</b>

<b>  // Получить объект File из объекта FileEntry из корневого DirectoryEntry</b>

<b>  var file = filesystem.root.getFile(name).file();</b>

<b>  // Использовать для чтения синхронную версию FileReader</b>

<b>  return new FileReaderSync().readAsText(file);</b>

<b>}</b>

<b>function appendToFile(name, contents) {</b>

<b>  // Получить FileWriter из FileEntry из корневого DirectoryEntry</b>

<b>  var writer = filesystem.root.getFile(name, {create:true}).createWriter();</b>

<b>  writer.seek(writer.length); // Начать запись с конца файла</b>

<b>  var bb = new BlobBuilder()  // Собрать содержимое в виде объекта Blob</b>

<b>  bb.append(contents);</b>

<b>  writer.write(bb.getBlob()); // Записать двоичный объект в файл</b>

<b>}</b>

<b>function deleteFile(name) {</b>

<b>  filesystem.root.getFile(name).remove();</b>

<b>}</b>

<b>function makeDirectory(name) {</b>

<b>  filesystem.root.getDirectory(name. { create: true, exclusive:true });</b>

<b>}</b>

<b>function listFiles(path) {</b>

<b>  var dir = filesystem.root;</b>

<b>  if (path) dir = dir.getDirectory(path);</b>

<b>  var lister = dir.createReader();</b>

<b>  var list = [];</b>

<b>  do {</b>

<b>    var entries = lister.readEntries();</b>

<b>    for(var і = 0; і &lt; entries.length; i++) {</b>

<b>      var name = entries[i].name;</b>

<b>      if (entries[i]. isDirectory) name += list.push(name);</b>

<b>    }</b>

<b>  } while(entries.length &gt; 0); return list;</b>

<b>}</b>

<b>// Разрешить основному потоку выполнения использовать эти утилиты, посылая сообщения</b>

<b>onmessage = function(e) {</b>

<b>  // Сообщение должно быть объектом:</b>

<b>  // { function: &quot;appendToFile&quot;, args: [&quot;test&quot;, &quot;testing, testing&quot;]}</b>

<b>  // Вызвать указанную функцию с указанными аргументами и послать сообщение обратно</b>

<b>  var f = self[e.data.function];</b>

<b>  var result = f.apply(null, e.data.args);</b>

<b>  postMessage(result);</b>

<b>};</b>

22.8. Базы данных на стороне клиента

Архитектура веб-приложений традиционно была основана на поддержке HTML, CSS и JavaScript на стороне клиента и базы данных на стороне сервера. Поэтому одним из самых удивительных прикладных интерфейсов, определяемых спецификацией HTML5, является поддержка баз данных на стороне клиента. Это не прикладные интерфейсы доступа к базам данных на стороне сервера, а действительно интерфейсы доступа к базам данных, хранящимся на компьютере клиента и доступным непосредственно из программного кода на языке JavaScript, выполняемого броузером.

Прикладной интерфейс веб-хранилища, определяемый спецификацией «Web Storage» и описанный в разделе 20.1, можно расценивать как простейшую разновидность базы данных, хранящую пары ключ/значение. Но помимо него имеются еще два прикладных интерфейса доступа к клиентским базам данных, которые являются «настоящими» базами данных. Один из них известен как «Web SQL Database» - простая реляционная база данных, поддерживающая простейшие SQL-запросы. Этот прикладной интерфейс реализован в броузерах Chrome, Safari и Opera. Он не реализован в Firefox и IE и, скорее всего, никогда не будет реализован в них. Работа над официальной спецификацией этого прикладного интерфейса была остановлена, и поддержка полноценной базы данных SQL, вероятно, никогда не приобретет статус официального стандарта или неофициальной, но широко поддерживаемой особенности веб-платформы.

В настоящее время все усилия по стандартизации сконцентрированы на другом прикладном интерфейсе к базам данных, известном как IndexedDB. Пока слишком рано описывать детали этого прикладного интерфейса (его описание отсутствует в четвертой части книги), но Firefox 4 и Chrome 11 включают его реализацию, и в этом разделе будет представлен действующий пример, демонстрирующий некоторые из наиболее важных особенностей прикладного интерфейса IndexedDB.

IndexedDB - это объектная, а не реляционная база данных, и она намного проще, чем базы данных, поддерживающие язык запросов SQL. Однако она гораздо мощнее, эффективнее и надежнее, чем веб-хранилище пар ключ/значение, доступное посредством прикладного интерфейса Web Storage. Как и в случае прикладных интерфейсов к веб-хранилищам и файловой системе, доступность базы данных IndexedDB определяется происхождением создавшего ее документа: две веб-страницы с общим происхождением могут обращаться к данным друг друга, но вебстраницы с разным происхождением - нет.

Для каждого происхождения может быть создано произвольное число баз данных IndexedDB. Каждая база данных имеет имя, которое должно быть уникальным для данного происхождения. С точки зрения прикладного интерфейса IndexedDB база данных является простой коллекцией именованных хранилищ объектов. Как следует из этого названия, хранилище объектов хранит объекты (или любые другие значения, которые можно копировать, - смотрите врезку «Структурированные копии» выше). Каждый объект должен иметь ключ, под которым он сохраняется и извлекается из хранилища. Ключи должны быть уникальными - два объекта в одном хранилище не могут иметь одинаковые ключи, - и они должны иметь естественный порядок следования, чтобы их можно было сортировать. Примерами допустимых ключей являются строки, числа и объекты

<b>Date</b>
. База данных IndexedDB может автоматически генерировать уникальные ключи для каждого объекта, добавляемого в базу данных. Однако часто объекты, сохраняемые в хранилище объектов, уже будут иметь свойство, пригодное для использования в качестве ключа. В этом случае при создании хранилища объектов достаточно просто определить «путь к ключу», определяющий это свойство. Концептуально, путь к ключу - это значение, сообщающее базе данных, как извлечь ключ из объекта.