Signatur
Beschreibung
IDBCursorWithValue.value liefert den Wert des Datensatzes, auf dem der Cursor gerade steht. Das kann jeder Wert sein, den der Structured-Clone-Algorithmus speichern kann: Objekte, Arrays, Strings, Zahlen, Date, Blob, Map und weitere.
Ein IDBCursorWithValue entsteht durch IDBObjectStore.openCursor() oder IDBIndex.openCursor(). Die Methoden openKeyCursor() liefern dagegen nur ein IDBCursor ohne value. Dieser Cursor ist schneller, wenn man nur Schlüssel braucht.
Bei jedem Schritt mit cursor.continue() oder cursor.advance(n) bekommt value den Wert des nächsten Datensatzes. Der zurückgegebene Wert ist eine Kopie. Wenn du ihn änderst, bleibt die Datenbank unverändert, bis du die Änderung mit cursor.update(value) oder store.put() zurückschreibst.
Typische Einsätze: alle Datensätze durchlaufen und filtern, Einträge nach Bedingungen ändern oder löschen und seitenweise Ausgaben über einen Index.
Rückgabewert
Beispiele
Alle Datensätze eines Object Stores ausgeben
const request = indexedDB.open('shop', 1);
request.onupgradeneeded = () => {
const db = request.result;
const store = db.createObjectStore('produkte', { keyPath: 'id' });
store.put({ id: 1, name: 'Tastatur', preis: 49 });
store.put({ id: 2, name: 'Maus', preis: 19 });
};
request.onsuccess = () => {
const db = request.result;
const store = db.transaction('produkte', 'readonly').objectStore('produkte');
store.openCursor().onsuccess = (event) => {
const cursor = event.target.result;
if (!cursor) {
console.log('Fertig');
return;
}
const { name, preis } = cursor.value;
console.log(`${cursor.key}: ${name} – ${preis} €`);
cursor.continue();
};
};
Werte ändern und mit update() zurückschreiben
const erhoehePreise = (db, prozent) => new Promise((resolve, reject) => {
const tx = db.transaction('produkte', 'readwrite');
const store = tx.objectStore('produkte');
store.openCursor().onsuccess = (event) => {
const cursor = event.target.result;
if (!cursor) return;
// value ist eine Kopie: ändern allein reicht nicht
const produkt = { ...cursor.value };
produkt.preis = Math.round(produkt.preis * (1 + prozent / 100));
cursor.update(produkt); // erst jetzt wird gespeichert
cursor.continue();
};
tx.oncomplete = () => resolve();
tx.onerror = () => reject(tx.error);
});
// Aufruf: await erhoehePreise(db, 10);
Datensätze mit async/await in ein Array sammeln
const alleWerte = (store, filter = () => true) => new Promise((resolve, reject) => {
const ergebnis = [];
const req = store.openCursor();
req.onsuccess = () => {
const cursor = req.result;
if (!cursor) return resolve(ergebnis);
if (filter(cursor.value)) ergebnis.push(cursor.value);
cursor.continue();
};
req.onerror = () => reject(req.error);
});
// Nutzung:
// const store = db.transaction('produkte').objectStore('produkte');
// const guenstig = await alleWerte(store, (p) => p.preis < 30);
// console.log(guenstig);
// Wichtig · Fallstricke
- Nur lesbar: Eine Zuweisung an
cursor.valuehat keine Wirkung. Um einen Datensatz zu ändern, nutzecursor.update(neuerWert). Das geht nur in einerreadwrite-Transaktion. - Kopie statt Referenz: Änderungen am zurückgegebenen Objekt werden nicht automatisch gespeichert. Klassen-Instanzen verlieren beim Klonen ihren Prototyp und kommen als einfache Objekte zurück.
- Cursor-Typ: Cursor aus
openKeyCursor()sind reineIDBCursor-Objekte und haben keinvalue, es ist dannundefined. Wenn du nur Schlüssel brauchst, ist das schneller. - Transaktion aktiv halten: Rufe
continue()synchron imonsuccess-Handler auf. Einawaitauf ein fremdes Promise dazwischen kann die Transaktion beenden. Danach gibt es einenTransactionInactiveError. - Performance: Wenn du alle Werte ohne Filterlogik brauchst, ist
IDBObjectStore.getAll()meist deutlich schneller als ein Cursor. - Kompatibilität: Wird in allen modernen Browsern und in Web Workern unterstützt. In privaten Fenstern mancher Browser kann IndexedDB eingeschränkt sein.