Bekerja dengan IndexedDB

Panduan ini membahas dasar-dasar tensorflow API. Kami menggunakan milik Jake Archibald Promise Dijanjikan library, yang sangat mirip dengan Responden API, tetapi menggunakan promise, Anda dapat melakukan await untuk sintaksis yang lebih ringkas. Hal ini menyederhanakan API sekaligus dan mempertahankan strukturnya.

iPhone adalah sistem penyimpanan NoSQL berskala besar yang memungkinkan penyimpanan tentang apa pun dalam {i>browser<i} pengguna. Selain penelusuran biasa, get, dan menempatkan tindakan, IndexedDB juga mendukung transaksi, dan sangat cocok untuk menyimpan data terstruktur dalam jumlah besar.

Setiap database Responden unik untuk origin (biasanya domain atau subdomain situs), yang berarti situs tersebut tidak dapat mengakses atau diakses oleh origin lainnya. Batas penyimpanan datanya biasanya berukuran besar, jika ada, tetapi browser yang berbeda menangani batasan dan penghapusan data secara berbeda. Lihat bagian Bacaan lebih lanjut untuk informasi selengkapnya.

Persyaratan IndexedDB

Database
Tingkat tertinggi pengguna. Isinya adalah tempat penyimpanan objek, yang kemudian berisi data yang ingin Anda pertahankan. Anda dapat membuat beberapa {i>database<i} dengan nama apa pun yang Anda pilih.
Penyimpanan objek
Bucket individual untuk menyimpan data, mirip dengan tabel dalam database relasional. Biasanya, ada satu penyimpanan objek untuk setiap jenis (bukan data JavaScript ) data yang Anda simpan. Tidak seperti dalam tabel {i>database<i}, data JavaScript tipe data dalam sebuah penyimpanan tidak harus konsisten. Misalnya, jika sebuah aplikasi memiliki penyimpanan objek people yang berisi informasi tentang tiga orang, yang properti usia orang dapat berupa 53, 'twenty-five', dan unknown.
Indeks
Semacam penyimpanan objek untuk mengatur data di penyimpanan objek lain (disebut penyimpanan objek referensi) dengan properti individual data. Indeks digunakan untuk mengambil kumpulan data di penyimpanan objek oleh properti ini. Misalnya, jika Anda menyimpan orang, Anda mungkin ingin mengambilnya nanti berdasarkan nama, usia, atau hewan favoritnya.
Operasi
Interaksi dengan database.
Transaksi
Wrapper di sekitar operasi atau grup operasi yang memastikan database integritas data. Jika salah satu tindakan dalam transaksi gagal, maka tidak satu pun diterapkan dan {i>database<i} kembali ke status sebelum transaksi dimulai. Semua operasi baca atau tulis di Responden harus merupakan bagian dari transaksi. Cara ini memungkinkan operasi baca-modifikasi-tulis atomik tanpa risiko konflik dengan thread lain yang bertindak pada database secara bersamaan.
Kursor
Mekanisme untuk melakukan iterasi pada beberapa record dalam sebuah database.

Cara memeriksa dukungan IndexedDB

tensorflow hampir didukung secara universal. Namun, jika Anda bekerja dengan {i>browser<i} lama, tidak baik untuk dukungan deteksi fitur untuk berjaga-jaga. Cara termudah adalah dengan memeriksa window :

function indexedDBStuff () {
  // Check for IndexedDB support:
  if (!('indexedDB' in window)) {
    // Can't use IndexedDB
    console.log("This browser doesn't support IndexedDB");
    return;
  } else {
    // Do IndexedDB stuff here:
    // ...
  }
}

// Run IndexedDB code:
indexedDBStuff();

Cara membuka database

Dengan tensorflow, Anda dapat membuat lebih dari satu database dengan nama apa pun yang dipilih. Jika sebuah {i>database<i} tidak ada ketika Anda mencoba membukanya, itu otomatis dibuat. Untuk membuka database, gunakan metode openDB() dari library idb:

import {openDB} from 'idb';

async function useDB () {
  // Returns a promise, which makes `idb` usable with async-await.
  const dbPromise = await openDB('example-database', version, events);
}

useDB();

Metode ini menampilkan promise yang di-resolve ke objek database. Saat menggunakan Metode openDB(), berikan nama, nomor versi, dan objek peristiwa yang akan ditetapkan mengubah {i>database<i}.

Berikut adalah contoh metode openDB() dalam konteks:

import {openDB} from 'idb';

async function useDB () {
  // Opens the first version of the 'test-db1' database.
  // If the database does not exist, it will be created.
  const dbPromise = await openDB('test-db1', 1);
}

useDB();

Tempatkan tanda centang untuk dukungan IndexedDB di bagian atas fungsi anonim. Ini keluar dari fungsi jika browser tidak mendukung IndexedDB. Jika fungsi tersebut dapat melanjutkan, tindakan ini akan memanggil metode openDB() untuk membuka database bernama 'test-db1'. Dalam contoh ini, objek peristiwa opsional diabaikan untuk mempertahankan sederhana, namun Anda perlu menetapkannya untuk melakukan pekerjaan apa pun yang berarti dengan IndexedDB.

Cara menggunakan penyimpanan objek

Database Responden berisi satu atau beberapa penyimpanan objek, yang masing-masing memiliki kolom untuk kunci, dan kolom lain untuk data yang terkait dengan kunci tersebut.

Membuat penyimpanan objek

Database Responden yang terstruktur dengan baik harus memiliki satu penyimpanan objek untuk setiap jenis data yang perlu dipertahankan. Misalnya, situs yang mempertahankan pengguna profil dan catatan mungkin memiliki penyimpanan objek people yang berisi person objek, dan penyimpanan objek notes yang berisi objek note.

Untuk memastikan integritas database, Anda hanya dapat membuat atau menghapus penyimpanan objek di peristiwa dalam panggilan openDB(). Objek peristiwa mengekspos upgrade() yang memungkinkan Anda membuat penyimpanan objek. Panggil createObjectStore() di dalam metode upgrade() untuk membuat penyimpanan objek:

import {openDB} from 'idb';

async function createStoreInDB () {
  const dbPromise = await openDB('example-database', 1, {
    upgrade (db) {
      // Creates an object store:
      db.createObjectStore('storeName', options);
    }
  });
}

createStoreInDB();

Metode ini mengambil nama penyimpanan objek dan konfigurasi opsional yang memungkinkan Anda menentukan berbagai properti untuk penyimpanan objek.

Berikut adalah contoh cara menggunakan createObjectStore():

import {openDB} from 'idb';

async function createStoreInDB () {
  const dbPromise = await openDB('test-db1', 1, {
    upgrade (db) {
      console.log('Creating a new object store...');

      // Checks if the object store exists:
      if (!db.objectStoreNames.contains('people')) {
        // If the object store does not exist, create it:
        db.createObjectStore('people');
      }
    }
  });
}

createStoreInDB();

Dalam contoh ini, objek peristiwa diteruskan ke metode openDB() untuk membuat penyimpanan objek, dan seperti sebelumnya, pekerjaan membuat penyimpanan objek sudah selesai dalam metode upgrade() objek peristiwa. Namun, karena browser menampilkan error jika Anda mencoba membuat penyimpanan objek yang sudah ada, sebaiknya menggabungkan metode createObjectStore() dalam pernyataan if yang memeriksa apakah penyimpanan objek sudah ada. Di dalam blok if, panggil createObjectStore() untuk membuat penyimpanan objek bernama 'firstOS'.

Cara menentukan kunci utama

Saat Anda mendefinisikan penyimpanan objek, Anda bisa menentukan bagaimana data diidentifikasi secara unik dalam store menggunakan {i>primary key<i}. Anda bisa mendefinisikan {i>primary key <i}dengan menentukan jalur kunci atau dengan menggunakan generator kunci.

Jalur kunci adalah properti yang selalu ada dan berisi nilai yang unik. Sebagai contoh, dalam kasus penyimpanan objek people, Anda dapat memilih jenis alamat email alamat sebagai jalur kunci:

import {openDB} from 'idb';

async function createStoreInDB () {
  const dbPromise = await openDB('test-db2', 1, {
    upgrade (db) {
      if (!db.objectStoreNames.contains('people')) {
        db.createObjectStore('people', { keyPath: 'email' });
      }
    }
  });
}

createStoreInDB();

Contoh ini membuat penyimpanan objek bernama 'people' dan menetapkan email sebagai kunci utama dalam opsi keyPath.

Anda juga dapat menggunakan generator kunci seperti autoIncrement. Generator kunci membuat nilai unik untuk setiap objek yang ditambahkan ke penyimpanan objek. Secara {i>default<i}, jika Anda tidak menentukan kunci, IndexedDB akan membuat kunci dan menyimpannya secara terpisah dari data.

Contoh berikut membuat penyimpanan objek bernama 'notes' dan menyetel untuk ditetapkan secara otomatis sebagai angka yang bertambah otomatis:

import {openDB} from 'idb';

async function createStoreInDB () {
  const dbPromise = await openDB('test-db2', 1, {
    upgrade (db) {
      if (!db.objectStoreNames.contains('notes')) {
        db.createObjectStore('notes', { autoIncrement: true });
      }
    }
  });
}

createStoreInDB();

Contoh berikut mirip dengan contoh sebelumnya, tetapi kali ini Nilai yang bertambah otomatis secara eksplisit ditetapkan ke properti bernama 'id'.

import {openDB} from 'idb';

async function createStoreInDB () {
  const dbPromise = await openDB('test-db2', 1, {
    upgrade (db) {
      if (!db.objectStoreNames.contains('logs')) {
        db.createObjectStore('logs', { keyPath: 'id', autoIncrement: true });
      }
    }
  });
}

createStoreInDB();

Pemilihan metode yang akan digunakan untuk menetapkan kunci bergantung pada data Anda. Jika data memiliki properti yang selalu unik, Anda dapat menjadikannya keyPath untuk menerapkan keunikan ini. Jika tidak, gunakan nilai yang bertambah otomatis.

Kode berikut membuat tiga penyimpanan objek yang mendemonstrasikan berbagai cara untuk menentukan kunci utama di penyimpanan objek:

import {openDB} from 'idb';

async function createStoresInDB () {
  const dbPromise = await openDB('test-db2', 1, {
    upgrade (db) {
      if (!db.objectStoreNames.contains('people')) {
        db.createObjectStore('people', { keyPath: 'email' });
      }

      if (!db.objectStoreNames.contains('notes')) {
        db.createObjectStore('notes', { autoIncrement: true });
      }

      if (!db.objectStoreNames.contains('logs')) {
        db.createObjectStore('logs', { keyPath: 'id', autoIncrement: true });
      }
    }
  });
}

createStoresInDB();

Cara menentukan indeks

Indeks adalah semacam penyimpanan objek yang digunakan untuk mengambil data dari referensi penyimpanan objek dengan properti tertentu. Indeks berada di dalam objek referensi menyimpan dan berisi data yang sama, tetapi menggunakan properti yang ditentukan sebagai jalur kunci alih-alih kunci utama penyimpanan referensi. Indeks harus dibuat saat Anda membuat penyimpanan objek, dan dapat digunakan untuk menentukan batasan unik pada memahami data Anda.

Untuk membuat indeks, panggil createIndex() pada instance penyimpanan objek:

import {openDB} from 'idb';

async function createIndexInStore() {
  const dbPromise = await openDB('storeName', 1, {
    upgrade (db) {
      const objectStore = db.createObjectStore('storeName');

      objectStore.createIndex('indexName', 'property', options);
    }
  });
}

createIndexInStore();

Metode ini membuat dan mengembalikan objek indeks. Metode createIndex() aktif instance penyimpanan objek mengambil nama indeks baru sebagai yang pertama dan argumen kedua mengacu pada properti pada data yang ingin Google Cloud. Argumen terakhir memungkinkan Anda mendefinisikan dua opsi yang menentukan bagaimana indeks beroperasi: unique dan multiEntry. Jika unique disetel ke true, indeks tidak mengizinkan nilai duplikat untuk kunci tunggal. Berikutnya, multiEntry menentukan perilaku createIndex() saat properti yang diindeks adalah array. Jika disetel ke true, createIndex() menambahkan entri dalam indeks untuk setiap array . Jika tidak, kode ini menambahkan satu entri yang berisi array.

Berikut contohnya:

import {openDB} from 'idb';

async function createIndexesInStores () {
  const dbPromise = await openDB('test-db3', 1, {
    upgrade (db) {
      if (!db.objectStoreNames.contains('people')) {
        const peopleObjectStore = db.createObjectStore('people', { keyPath: 'email' });

        peopleObjectStore.createIndex('gender', 'gender', { unique: false });
        peopleObjectStore.createIndex('ssn', 'ssn', { unique: true });
      }

      if (!db.objectStoreNames.contains('notes')) {
        const notesObjectStore = db.createObjectStore('notes', { autoIncrement: true });

        notesObjectStore.createIndex('title', 'title', { unique: false });
      }

      if (!db.objectStoreNames.contains('logs')) {
        const logsObjectStore = db.createObjectStore('logs', { keyPath: 'id', autoIncrement: true });
      }
    }
  });
}

createIndexesInStores();

Dalam contoh ini, penyimpanan objek 'people' dan 'notes' memiliki indeks. Kepada membuat indeks, pertama-tama tetapkan hasil createObjectStore() (objek simpan objek) ke variabel sehingga Anda dapat memanggil createIndex() pada variabel tersebut.

Cara bekerja dengan data

Bagian ini menjelaskan cara membuat, membaca, memperbarui, dan menghapus data. Ini semua operasinya asinkron, menggunakan promise yang digunakan oleh API IndexedDB permintaan. Hal ini menyederhanakan API. Alih-alih memproses peristiwa yang dipicu oleh permintaan, Anda dapat memanggil .then() pada objek database yang ditampilkan dari openDB() untuk memulai interaksi dengan database, atau await pembuatan konten.

Semua operasi data di IndexedDB dilakukan di dalam transaksi. Masing-masing operasi memiliki bentuk berikut:

  1. Mendapatkan objek database.
  2. Buka transaksi di database.
  3. Buka penyimpanan objek saat transaksi.
  4. Menjalankan operasi pada penyimpanan objek.

Transaksi dapat dianggap sebagai wrapper yang aman di sekitar operasi atau grup operasional bisnis. Jika salah satu tindakan dalam transaksi gagal, semua tindakan di-roll back. Transaksi bersifat khusus untuk satu atau lebih penyimpanan objek, yang Anda tentukan saat membuka transaksi. Dapat berupa hanya-baca atau baca dan tulis. Ini menandakan bahwa operasi di dalam transaksi membaca data atau membuat perubahan pada {i>database<i}.

Membuat data

Untuk membuat data, panggil add() pada instance database dan meneruskan data yang ingin Anda tambahkan. add() argumen pertama metode ini adalah penyimpanan objek yang ingin Anda tambahi data, dan adalah objek yang berisi kolom dan data terkait yang Anda inginkan untuk ditambahkan. Berikut adalah contoh paling sederhana, dengan satu baris data ditambahkan:

import {openDB} from 'idb';

async function addItemToStore () {
  const db = await openDB('example-database', 1);

  await db.add('storeName', {
    field: 'data'
  });
}

addItemToStore();

Setiap panggilan add() terjadi dalam transaksi, jadi meskipun promise di-resolve berhasil, bukan berarti operasi telah berhasil. Untuk memastikan operasi penjumlahan telah dilakukan, Anda perlu memeriksa apakah seluruh transaksi telah selesai menggunakan metode transaction.done(). Ini adalah promise yang selesai ketika transaksi selesai dengan sendirinya, dan menolak jika error transaksi. Anda harus melakukan pemeriksaan ini untuk semua "tulis" operasional, karena itu adalah satu-satunya cara untuk mengetahui bahwa perubahan pada {i>database<i} sebenarnya terjadi.

Kode berikut menunjukkan penggunaan metode add() di dalam transaksi:

import {openDB} from 'idb';

async function addItemsToStore () {
  const db = await openDB('test-db4', 1, {
    upgrade (db) {
      if (!db.objectStoreNames.contains('foods')) {
        db.createObjectStore('foods', { keyPath: 'name' });
      }
    }
  });
  
  // Create a transaction on the 'foods' store in read/write mode:
  const tx = db.transaction('foods', 'readwrite');

  // Add multiple items to the 'foods' store in a single transaction:
  await Promise.all([
    tx.store.add({
      name: 'Sandwich',
      price: 4.99,
      description: 'A very tasty sandwich!',
      created: new Date().getTime(),
    }),
    tx.store.add({
      name: 'Eggs',
      price: 2.99,
      description: 'Some nice eggs you can cook up!',
      created: new Date().getTime(),
    }),
    tx.done
  ]);
}

addItemsToStore();

Setelah membuka {i>database<i} (dan membuat penyimpanan objek jika diperlukan), Anda perlu untuk membuka transaksi dengan memanggil metode transaction() di transaksi tersebut. Metode ini mengambil argumen untuk toko tempat Anda ingin bertransaksi, serta modenya. Dalam hal ini, kita tertarik untuk menulis ke toko, jadi contoh ini menentukan 'readwrite'.

Langkah berikutnya adalah mulai menambahkan item ke toko sebagai bagian dari transaksi. Pada contoh sebelumnya, kita menangani tiga operasi pada 'foods' simpan yang masing-masing menampilkan promise:

  1. Menambahkan catatan untuk sandwich lezat.
  2. Menambahkan catatan untuk beberapa telur.
  3. Memberi sinyal bahwa transaksi selesai (tx.done).

Karena semua tindakan ini berbasis promise, kita harus menunggu mereka untuk menyelesaikannya. Meneruskan janji ini kepada Promise.all adalah cara yang ergonomis dan bagus untuk menyelesaikan tugas ini. Promise.all menerima array promise dan selesai ketika semua promise yang diteruskan kepadanya telah diselesaikan.

Untuk dua data yang ditambahkan, antarmuka store instance transaksi memanggil add() dan meneruskan data ke dalamnya. Anda dapat await panggilan Promise.all sehingga selesai ketika transaksi selesai.

Membaca data

Untuk membaca data, panggil get() pada instance database yang Anda ambil menggunakan metode openDB(). get() mengambil nama penyimpanan dan nilai kunci utama objek yang Anda yang ingin diambil. Berikut adalah contoh dasarnya:

import {openDB} from 'idb';

async function getItemFromStore () {
  const db = await openDB('example-database', 1);

  // Get a value from the object store by its primary key value:
  const value = await db.get('storeName', 'unique-primary-key-value');
}

getItemFromStore();

Seperti halnya add(), metode get() akan menampilkan promise, sehingga Anda dapat melakukan await jika yang Anda inginkan, atau gunakan callback .then() promise.

Contoh berikut menggunakan metode get() di database 'test-db4' 'foods' untuk mendapatkan satu baris berdasarkan kunci utama 'name':

import {openDB} from 'idb';

async function getItemFromStore () {
  const db = await openDB('test-db4', 1);
  const value = await db.get('foods', 'Sandwich');

  console.dir(value);
}

getItemFromStore();

Mengambil satu baris dari {i>database<i} cukup mudah: terbuka {i>database<i} dan tentukan penyimpanan objek dan nilai kunci utama dari baris yang Anda yang ingin kita dapatkan datanya. Karena metode get() menampilkan promise, Anda dapat await-nya.

Memperbarui data

Untuk memperbarui data, panggil put() pada penyimpanan objek. Metode put() mirip dengan metode add() dan juga dapat digunakan sebagai pengganti add() untuk membuat data. Berikut adalah contoh dasar penggunaan put() untuk memperbarui baris dalam penyimpanan objek berdasarkan nilai kunci utamanya:

import {openDB} from 'idb';

async function updateItemInStore () {
  const db = await openDB('example-database', 1);

  // Update a value from in an object store with an inline key:
  await db.put('storeName', { inlineKeyName: 'newValue' });

  // Update a value from in an object store with an out-of-line key.
  // In this case, the out-of-line key value is 1, which is the
  // auto-incremented value.
  await db.put('otherStoreName', { field: 'value' }, 1);
}

updateItemInStore();

Seperti metode lain, metode ini akan menampilkan promise. Anda juga dapat menggunakan put() sebagai dari transaksi. Berikut contoh yang menggunakan penyimpanan 'foods' dari versi sebelumnya yang memperbarui harga roti dan telur:

import {openDB} from 'idb';

async function updateItemsInStore () {
  const db = await openDB('test-db4', 1);
  
  // Create a transaction on the 'foods' store in read/write mode:
  const tx = db.transaction('foods', 'readwrite');

  // Update multiple items in the 'foods' store in a single transaction:
  await Promise.all([
    tx.store.put({
      name: 'Sandwich',
      price: 5.99,
      description: 'A MORE tasty sandwich!',
      updated: new Date().getTime() // This creates a new field
    }),
    tx.store.put({
      name: 'Eggs',
      price: 3.99,
      description: 'Some even NICER eggs you can cook up!',
      updated: new Date().getTime() // This creates a new field
    }),
    tx.done
  ]);
}

updateItemsInStore();

Cara item diperbarui bergantung pada cara Anda menetapkan kunci. Jika Anda menetapkan keyPath, setiap baris di penyimpanan objek dikaitkan dengan tombol inline. Sebelumnya contoh ini memperbarui baris berdasarkan kunci ini, dan saat Anda memperbarui baris di ini, Anda harus menentukan kunci itu untuk memperbarui item yang sesuai di penyimpanan objek. Anda juga dapat membuat kunci out-of-line dengan menyetel autoIncrement sebagai kunci utama.

Menghapus data

Untuk menghapus data, panggil delete() pada penyimpanan objek:

import {openDB} from 'idb';

async function deleteItemFromStore () {
  const db = await openDB('example-database', 1);

  // Delete a value 
  await db.delete('storeName', 'primary-key-value');
}

deleteItemFromStore();

Seperti add() dan put(), Anda dapat menggunakannya sebagai bagian dari transaksi:

import {openDB} from 'idb';

async function deleteItemsFromStore () {
  const db = await openDB('test-db4', 1);
  
  // Create a transaction on the 'foods' store in read/write mode:
  const tx = db.transaction('foods', 'readwrite');

  // Delete multiple items from the 'foods' store in a single transaction:
  await Promise.all([
    tx.store.delete('Sandwich'),
    tx.store.delete('Eggs'),
    tx.done
  ]);
}

deleteItemsFromStore();

Struktur interaksi {i>database<i} sama dengan yang lainnya operasional bisnis. Ingatlah untuk memeriksa apakah seluruh transaksi telah diselesaikan oleh termasuk metode tx.done dalam array yang Anda teruskan ke Promise.all.

Mendapatkan semua data

Sejauh ini, Anda hanya mengambil objek dari toko satu per satu. Anda juga dapat mengambil semua data, atau {i>subset<i}, dari penyimpanan objek atau indeks menggunakan metode getAll() atau kursor.

Metode getAll()

Cara termudah untuk mengambil semua data penyimpanan objek adalah dengan memanggil getAll() pada penyimpanan atau indeks objek, seperti ini:

import {openDB} from 'idb';

async function getAllItemsFromStore () {
  const db = await openDB('test-db4', 1);

  // Get all values from the designated object store:
  const allValues = await db.getAll('storeName');

  console.dir(allValues);
}

getAllItemsFromStore();

Metode ini menampilkan semua objek dalam penyimpanan objek, tanpa batasan apa pun itu. Ini adalah cara paling langsung untuk mendapatkan semua nilai dari penyimpanan objek, tetapi juga yang paling tidak fleksibel.

import {openDB} from 'idb';

async function getAllItemsFromStore () {
  const db = await openDB('test-db4', 1);

  // Get all values from the designated object store:
  const allValues = await db.getAll('foods');

  console.dir(allValues);
}

getAllItemsFromStore();

Contoh ini memanggil getAll() di penyimpanan objek 'foods'. Proses ini akan mengembalikan semua objek dari 'foods', yang diurutkan berdasarkan kunci utama.

Cara menggunakan kursor

Kursor adalah cara yang lebih fleksibel untuk mengambil beberapa objek. Kursor memilih setiap objek dalam objek yang disimpan atau diindeks satu per satu, memungkinkan Anda untuk dengan data saat dipilih. Kursor, seperti operasi {i>database<i} lainnya, bekerja dalam transaksi.

Untuk membuat kursor, panggil openCursor() di penyimpanan objek sebagai bagian dari transaksi. Menggunakan penyimpanan 'foods' dari contoh sebelumnya, ini adalah cara untuk memajukan kursor melalui semua baris data dalam penyimpanan objek:

import {openDB} from 'idb';

async function getAllItemsFromStoreWithCursor () {
  const db = await openDB('test-db4', 1);
  const tx = await db.transaction('foods', 'readonly');

  // Open a cursor on the designated object store:
  let cursor = await tx.store.openCursor();

  // Iterate on the cursor, row by row:
  while (cursor) {
    // Show the data in the row at the current cursor position:
    console.log(cursor.key, cursor.value);

    // Advance the cursor to the next row:
    cursor = await cursor.continue();
  }
}

getAllItemsFromStoreWithCursor();

Transaksi dalam kasus ini dibuka dalam mode 'readonly', dan Metode openCursor dipanggil. Dalam loop while berikutnya, baris di posisi kursor saat ini dapat membuat properti key dan value dibaca, dan Anda dapat beroperasi pada nilai-nilai tersebut dengan cara apa pun yang paling masuk akal bagi . Setelah siap, Anda dapat memanggil continue() objek cursor untuk menuju ke baris berikutnya, dan loop while akan berakhir saat kursor mencapai akhir {i>dataset<i}.

Menggunakan kursor dengan rentang dan indeks

Indeks memungkinkan Anda mengambil data dalam objek yang disimpan oleh properti selain {i>primary key<i}-nya. Anda dapat membuat indeks di properti mana pun, yang menjadi keyPath untuk indeks, tentukan rentang pada properti itu, dan dapatkan data di dalam rentang menggunakan getAll() atau kursor.

Tentukan rentang Anda menggunakan objek IDBKeyRange. dan salah satu dari yang berikut metode:

Metode upperBound() dan lowerBound() menentukan batas atas dan bawah dari rentang tersebut.

IDBKeyRange.lowerBound(indexKey);

Atau:

IDBKeyRange.upperBound(indexKey);

Masing-masing mengambil satu argumen: nilai keyPath indeks untuk item yang Anda inginkan untuk ditetapkan sebagai batas atas atau bawah.

Metode bound() menentukan batas atas dan bawah:

IDBKeyRange.bound(lowerIndexKey, upperIndexKey);

Rentang untuk fungsi ini bersifat inklusif secara {i>default<i}, artinya mencakup data yang ditentukan sebagai batas rentang. Untuk menghilangkan nilai-nilai tersebut, tentukan rentang sebagai eksklusif dengan meneruskan true sebagai argumen kedua untuk lowerBound() atau upperBound(), atau sebagai argumen ketiga dan keempat dari bound(), untuk batas bawah dan atas.

Contoh berikutnya menggunakan indeks pada properti 'price' dalam objek 'foods' Anda. Sekarang, Play Store juga memiliki formulir yang terlampir dengan dua input untuk batas atas dan bawah rentang. Gunakan kode berikut untuk menemukan makanan dengan harga di antara batas tersebut:

import {openDB} from 'idb';

async function searchItems (lower, upper) {
  if (!lower === '' && upper === '') {
    return;
  }

  let range;

  if (lower !== '' && upper !== '') {
    range = IDBKeyRange.bound(lower, upper);
  } else if (lower === '') {
    range = IDBKeyRange.upperBound(upper);
  } else {
    range = IDBKeyRange.lowerBound(lower);
  }

  const db = await openDB('test-db4', 1);
  const tx = await db.transaction('foods', 'readonly');
  const index = tx.store.index('price');

  // Open a cursor on the designated object store:
  let cursor = await index.openCursor(range);

  if (!cursor) {
    return;
  }

  // Iterate on the cursor, row by row:
  while (cursor) {
    // Show the data in the row at the current cursor position:
    console.log(cursor.key, cursor.value);

    // Advance the cursor to the next row:
    cursor = await cursor.continue();
  }
}

// Get items priced between one and four dollars:
searchItems(1.00, 4.00);

Kode contoh terlebih dahulu mendapatkan nilai untuk batas dan memeriksa apakah batas tersebut ada. Blok kode berikutnya memutuskan metode mana yang akan digunakan untuk membatasi rentang berdasarkan nilai-nilai tersebut. Dalam interaksi database, buka penyimpanan objek di seperti biasa, lalu buka indeks 'price' di penyimpanan objek. Tujuan Indeks 'price' memungkinkan Anda menelusuri item berdasarkan harga.

Kode tersebut kemudian membuka kursor pada indeks dan meneruskan rentang tersebut. Kursor menampilkan promise yang mewakili objek pertama dalam rentang, atau undefined jika tidak ada data dalam rentang. Metode cursor.continue() akan menampilkan kursor yang mewakili objek berikutnya, dan berlanjut melalui loop sampai Anda mencapai akhir rentang.

Pembuatan versi database

Saat memanggil metode openDB(), Anda dapat menentukan nomor versi database di parameter kedua. Dalam semua contoh dalam panduan ini, versinya telah ditetapkan ke 1, tetapi database dapat diupgrade ke versi baru jika perlu memodifikasinya dalam beberapa cara. Jika versi yang ditentukan lebih besar dari versi database yang ada, callback upgrade di objek peristiwa akan dieksekusi, memungkinkan Anda untuk menambahkan penyimpanan dan indeks objek baru ke {i>database<i}.

Objek db dalam callback upgrade memiliki properti oldVersion khusus, yang menunjukkan nomor versi {i>database<i} yang dapat diakses oleh {i>browser<i}. Anda dapat meneruskan nomor versi ini ke dalam pernyataan switch untuk mengeksekusi blok kode di dalam callback upgrade berdasarkan versi database yang sudah ada angka Berikut contohnya:

import {openDB} from 'idb';

const db = await openDB('example-database', 2, {
  upgrade (db, oldVersion) {
    switch (oldVersion) {
      case 0:
        // Create first object store:
        db.createObjectStore('store', { keyPath: 'name' });

      case 1:
        // Get the original object store, and create an index on it:
        const tx = await db.transaction('store', 'readwrite');
        tx.store.createIndex('name', 'name');
    }
  }
});

Contoh ini menetapkan versi terbaru database ke 2. Jika kode ini pertama kali dijalankan, database belum ada di browser, sehingga oldVersion adalah 0, dan pernyataan switch dimulai pada case 0. Pada contoh, menambahkan penyimpanan objek 'store' ke database.

Poin utama: Dalam pernyataan switch, biasanya ada break setelah setiap case Namun, blok ini sengaja tidak digunakan di sini. Dengan cara ini, jika kebijakan yang ada tertinggal beberapa versi, atau jika database tidak ada, kode melewati sisa blok case sampai terbaru. Dalam contoh ini, browser terus mengeksekusi case 1, sehingga membuat indeks name di penyimpanan objek store.

Untuk membuat indeks 'description' pada penyimpanan objek 'store', perbarui metode nomor versi dan tambahkan blok case baru sebagai berikut:

import {openDB} from 'idb';

const db = await openDB('example-database', 3, {
  upgrade (db, oldVersion) {
    switch (oldVersion) {
      case 0:
        // Create first object store:
        db.createObjectStore('store', { keyPath: 'name' });

      case 1:
        // Get the original object store, and create an index on it:
        const tx = await db.transaction('store', 'readwrite');
        tx.store.createIndex('name', 'name');

      case 2:
        const tx = await db.transaction('store', 'readwrite');
        tx.store.createIndex('description', 'description');
    }
  }
});

Jika {i>database<i} yang Anda buat di contoh sebelumnya masih ada di browser, saat kueri ini dijalankan, oldVersion adalah 2. Browser akan melewati case 0 dan case 1, dan mengeksekusi kode di case 2, yang membuat description Google Cloud. Setelah itu, browser memiliki database di versi 3 yang berisi store penyimpanan objek dengan indeks name dan description.

Bacaan lebih lanjut

Sumber bacaan berikut memberikan lebih banyak informasi dan konteks untuk menggunakan IndexedDB.

Dokumentasi IndexedDB

Batas penyimpanan data