Start · Sprachen · JavaScript · Referenz · IDBFactory.cmp()

IDBFactory.cmp()

Methode

Vergleicht zwei Werte nach den Sortierregeln von IndexedDB-Schlüsseln und gibt <code>-1</code>, <code>0</code> oder <code>1</code> zurück.

seit JavaScript Baseline: alle Browser (seit 2015) Kategorie: webapi

Signatur

IDBFactory.prototype.cmp(first, second)

Beschreibung

Die Methode cmp() des Interfaces IDBFactory (in der Praxis meist über indexedDB.cmp() aufgerufen) vergleicht zwei Werte genau so, wie IndexedDB Schlüssel intern vergleicht. Das Ergebnis zeigt, ob der erste Schlüssel kleiner, gleich oder größer als der zweite ist. So erfahren Sie, in welcher Reihenfolge Datensätze in einem Object Store oder Index abgelegt werden und ob zwei Schlüssel als identisch gelten.

IndexedDB kennt eine feste Typ-Reihenfolge: Number < Date < String < Binärdaten (ArrayBuffer, typisierte Arrays, DataView) < Array. Innerhalb eines Typs wird nach Wert verglichen. Zeichenketten vergleicht IndexedDB anhand ihrer UTF-16-Codeeinheiten, also nicht sprachabhängig. Arrays werden Element für Element verglichen, deshalb eignet sich die Methode gut für zusammengesetzte Schlüssel.

Typische Einsatzfälle:

  • Clientseitig vorab sortierte Daten in derselben Reihenfolge erzeugen, die auch ein Cursor liefern würde.
  • Schlüsselbereiche (IDBKeyRange) prüfen, bevor man sie anlegt. Ist die Untergrenze größer als die Obergrenze, wirft IDBKeyRange.bound() einen Fehler.
  • Prüfen, ob ein Wert überhaupt ein gültiger Schlüssel ist. Bei ungültigen Werten wirft cmp() eine Ausnahme.

Der Aufruf läuft synchron und öffnet keine Datenbank. Sie brauchen dafür weder eine Transaktion noch eine offene Verbindung.

Parameter

Name Typ Default Beschreibung
$first Pflicht number|Date|string|ArrayBuffer|ArrayBufferView|Array Erster Schlüssel, der verglichen wird. Er muss ein gültiger IndexedDB-Schlüssel sein.
$second Pflicht number|Date|string|ArrayBuffer|ArrayBufferView|Array Zweiter Schlüssel, der verglichen wird. Auch er muss ein gültiger IndexedDB-Schlüssel sein.

Rückgabewert

Typ
number
Beschreibung
-1, wenn first kleiner als second ist, 0 bei Gleichheit und 1, wenn first größer ist.

Beispiele

Grundlegende Vergleiche

console.log(indexedDB.cmp(1, 2));        // kleiner
console.log(indexedDB.cmp('abc', 'abc')); // gleich
console.log(indexedDB.cmp('b', 'a'));     // größer

// Typ-Reihenfolge: Number < Date < String < Binär < Array
console.log(indexedDB.cmp(9999, new Date(0)));
console.log(indexedDB.cmp('zzz', [0]));

// Strings nach UTF-16-Codeeinheiten: 'Z' (90) < 'a' (97)
console.log(indexedDB.cmp('Z', 'a'));
-1 0 1 -1 -1 -1

Zusammengesetzte Schlüssel (Arrays) vergleichen

// z. B. Index über [jahr, kategorie]
console.log(indexedDB.cmp([2024, 'buch'], [2024, 'auto'])); // 2. Element entscheidet
console.log(indexedDB.cmp([2023, 'zoo'], [2024, 'auto'])); // 1. Element entscheidet
console.log(indexedDB.cmp([1], [1, 2]));                   // kürzeres Präfix ist kleiner
1 -1 -1

Daten in IndexedDB-Reihenfolge sortieren

const keys = ['b', 3, [1], new Date(0), 'a', 1];

// Gleiche Reihenfolge, die ein Cursor über diese Schlüssel liefern würde
const sorted = [...keys].sort((a, b) => indexedDB.cmp(a, b));

console.log(sorted.map(k => (k instanceof Date ? 'Date' : JSON.stringify(k))));
["1", "3", "Date", "\"a\"", "\"b\"", "[1]"]

Gültigkeit von Schlüsseln prüfen und Key-Range absichern

const isValidKey = (value) => {
  try {
    indexedDB.cmp(value, 0);
    return true;
  } catch (err) {
    if (err.name === 'DataError') return false;
    throw err;
  }
};

console.log(isValidKey('user-42'));          // true
console.log(isValidKey(null));               // false
console.log(isValidKey(true));               // false
console.log(isValidKey(NaN));                // false
console.log(isValidKey(new Date('kaputt'))); // false

// Grenzen vor IDBKeyRange.bound() in die richtige Reihenfolge bringen
const safeBound = (a, b) =>
  indexedDB.cmp(a, b) <= 0 ? IDBKeyRange.bound(a, b) : IDBKeyRange.bound(b, a);

const range = safeBound('m', 'c');
console.log(range.lower, range.upper);
true false false false false c m

// Wichtig · Fallstricke

  • Ausnahmen: Ist einer der beiden Werte kein gültiger Schlüssel, wirft cmp() eine DOMException mit dem Namen DataError. Ungültig sind zum Beispiel null, undefined, boolean, einfache Objekte, NaN, ungültige Date-Objekte sowie Arrays mit ungültigen oder zirkulären Elementen. Übergeben Sie weniger als zwei Argumente, wird ein TypeError geworfen.
  • Keine sprachabhängige Sortierung: Strings werden nach UTF-16-Codeeinheiten verglichen. Deshalb gilt 'Z' < 'a' und 'ä' > 'z'. Für eine Sortierung, die Menschen erwarten, verwenden Sie Intl.Collator oder localeCompare(). Beachten Sie aber, dass IndexedDB selbst immer nach Codeeinheiten sortiert.
  • Typen werden nicht umgewandelt: indexedDB.cmp(1, '1') ergibt -1 und nicht 0. Zahl und String sind also verschiedene Schlüssel.
  • -0 und 0 gelten als gleich. Infinity und -Infinity sind gültige Schlüssel.
  • Binärschlüssel (ArrayBuffer und Views) werden in allen aktuellen Browsern unterstützt, in sehr alten Versionen aber nicht.
  • Die Methode steht auch in Web Workers zur Verfügung (self.indexedDB.cmp()). In manchen privaten Browser-Modi kann indexedDB eingeschränkt sein. cmp() selbst funktioniert aber ohne Speicherzugriff.