Start · Sprachen · JavaScript · Referenz · IDBObjectStore.count()

IDBObjectStore.count()

Methode

Zählt asynchron die Datensätze eines Object Stores, die zu einem Schlüssel oder einem <code>IDBKeyRange</code> passen, und liefert das Ergebnis über ein <code>IDBRequest</code>.

seit JavaScript Baseline: alle Browser (IndexedDB 2.0) Kategorie: webapi

Signatur

IDBObjectStore.prototype.count(query)

Beschreibung

Mit count() fragt man ab, wie viele Datensätze ein IDBObjectStore enthält. Ohne Argument werden alle Datensätze gezählt. Mit einem einzelnen Schlüssel oder einem IDBKeyRange werden nur die Datensätze gezählt, deren Primärschlüssel passt. Der Aufruf blockiert nicht: Zurück kommt sofort ein IDBRequest, und die Anzahl steht erst im success-Ereignis in request.result bereit.

Die Methode eignet sich zum Beispiel für Zähler in der Oberfläche („42 ungelesene Nachrichten“), für die Prüfung, ob ein Store leer ist, oder zum Berechnen der Seitenanzahl bei einer Paginierung. Die Werte selbst werden dabei nicht geladen. Das ist deutlich günstiger als getAll() und danach .length.

Der Aufruf braucht eine aktive Transaktion, entweder "readonly" oder "readwrite". Soll nach einem anderen Feld als dem Primärschlüssel gezählt werden, verwendet man IDBIndex.prototype.count() auf einem passenden Index.

Parameter

Name Typ Default Beschreibung
$query any | IDBKeyRange undefined (alle Datensätze) Ein gültiger Schlüssel (z. B. number, string, Date, Array) oder ein IDBKeyRange. Gezählt werden nur Datensätze, deren Primärschlüssel dazu passt. Ohne Angabe (oder mit null) wird der ganze Store gezählt.

Rückgabewert

Typ
IDBRequest<number>
Beschreibung
Ein IDBRequest. War der Aufruf erfolgreich, enthält request.result die Anzahl der passenden Datensätze als ganze Zahl (number).

Beispiele

Alle Datensätze eines Stores zählen

const openReq = indexedDB.open('shop', 1);

openReq.onupgradeneeded = () => {
  const db = openReq.result;
  const store = db.createObjectStore('produkte', { keyPath: 'id' });
  store.add({ id: 1, name: 'Tasse' });
  store.add({ id: 2, name: 'Teller' });
  store.add({ id: 3, name: 'Gabel' });
};

openReq.onsuccess = () => {
  const db = openReq.result;
  const tx = db.transaction('produkte', 'readonly');
  const countReq = tx.objectStore('produkte').count();

  countReq.onsuccess = () => {
    console.log(`Produkte im Store: ${countReq.result}`);
  };
  countReq.onerror = () => console.error(countReq.error);
};
Produkte im Store: 3

Nur einen Schlüsselbereich zählen (IDBKeyRange)

// Annahme: Store 'produkte' mit den IDs 1 bis 3 (siehe oben)
const countRange = (db) => {
  const store = db.transaction('produkte').objectStore('produkte');
  // IDs von 2 bis einschließlich 10
  const req = store.count(IDBKeyRange.bound(2, 10));
  req.onsuccess = () => console.log('IDs 2–10:', req.result);

  // Einzelner Schlüssel: 0 oder 1 – praktisch als Existenzprüfung
  const single = store.count(1);
  single.onsuccess = () => console.log('ID 1 vorhanden:', single.result === 1);
};
IDs 2–10: 2 ID 1 vorhanden: true

Promise-Wrapper mit async/await für eine Paginierung

const requestToPromise = (req) =>
  new Promise((resolve, reject) => {
    req.onsuccess = () => resolve(req.result);
    req.onerror = () => reject(req.error);
  });

const getPageCount = async (db, storeName, pageSize = 20) => {
  const store = db.transaction(storeName, 'readonly').objectStore(storeName);
  const total = await requestToPromise(store.count());
  return Math.max(1, Math.ceil(total / pageSize));
};

// Verwendung:
// const seiten = await getPageCount(db, 'produkte', 2);
// console.log(`Seiten: ${seiten}`);
Seiten: 2

// Wichtig · Fallstricke

  • Nur Primärschlüssel: query wird immer mit dem Primärschlüssel verglichen. Zum Zählen nach anderen Feldern (z. B. status === 'offen') legt man einen Index an und ruft store.index('status').count('offen') auf.
  • Ausnahmen: Ein ungültiger Schlüssel (z. B. ein Objekt oder NaN) löst sofort einen DataError aus. Ist die Transaktion schon beendet, kommt ein TransactionInactiveError. Wurde der Store gelöscht, kommt ein InvalidStateError.
  • Transaktion und await: Eine IndexedDB-Transaktion schließt sich automatisch, sobald keine Anfragen mehr offen sind. Wartet man zwischen den Anfragen auf fremde Promises (z. B. einen fetch-Aufruf), ist die Transaktion danach inaktiv und count() schlägt fehl.
  • Momentaufnahme: Die Anzahl gilt nur für den Zustand innerhalb dieser Transaktion. Spätere Schreibvorgänge, auch aus anderen Tabs, sind darin nicht enthalten.
  • Kompatibilität: Wird von allen aktuellen Browsern und in Web Workern unterstützt. Im privaten Modus älterer Safari- und Firefox-Versionen war IndexedDB teilweise gesperrt, deshalb sollte man Fehler beim Öffnen der Datenbank abfangen.