Signatur
Beschreibung
Die Eigenschaft source eines IDBCursor (bzw. IDBCursorWithValue) verweist auf das Objekt, auf dem der Cursor geöffnet wurde. Wurde er mit IDBObjectStore.openCursor() oder openKeyCursor() erzeugt, ist das ein IDBObjectStore. Wurde er mit IDBIndex.openCursor() oder openKeyCursor() erzeugt, ist es ein IDBIndex.
Nützlich ist das vor allem in allgemein gehaltenen Hilfsfunktionen, die einen Cursor als Argument bekommen und nicht wissen, woher er stammt. Über cursor.source kommt man an den Namen des Stores oder Index, am Index an keyPath oder über source.objectStore an den zugehörigen Object Store.
Die Eigenschaft ist nur lesbar und bleibt für den Cursor immer gleich. Sie gibt nie null zurück, solange der Cursor existiert. Auf den zurückgegebenen Store oder Index kann man aber nur zugreifen, solange die zugehörige Transaktion aktiv ist.
Rückgabewert
Beispiele
Quelle eines Store-Cursors ausgeben
const request = indexedDB.open('shop', 1);
request.onupgradeneeded = () => {
const db = request.result;
const store = db.createObjectStore('produkte', { keyPath: 'id' });
store.createIndex('nachPreis', 'preis');
store.add({ id: 1, name: 'Tasse', preis: 8 });
store.add({ id: 2, name: 'Teller', preis: 12 });
};
request.onsuccess = () => {
const db = request.result;
const tx = db.transaction('produkte', 'readonly');
const store = tx.objectStore('produkte');
store.openCursor().onsuccess = (event) => {
const cursor = event.target.result;
if (!cursor) return;
console.log(cursor.source instanceof IDBObjectStore, cursor.source.name);
cursor.continue();
};
};
Allgemeine Hilfsfunktion: Store oder Index erkennen
// Gibt für jeden Cursor aus, woher er stammt
const beschreibeQuelle = (cursor) => {
const { source } = cursor;
if (source instanceof IDBIndex) {
return `Index "${source.name}" auf Store "${source.objectStore.name}" (keyPath: ${source.keyPath})`;
}
return `Object Store "${source.name}"`;
};
const request = indexedDB.open('shop', 1);
request.onsuccess = () => {
const db = request.result;
const tx = db.transaction('produkte');
const index = tx.objectStore('produkte').index('nachPreis');
index.openCursor().onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
console.log(beschreibeQuelle(cursor), cursor.value.name);
cursor.continue();
}
};
};
Über einen Index-Cursor Datensätze löschen
// Löscht alle Produkte unter 10 € über den Preis-Index
const loescheGuenstige = (db) => new Promise((resolve, reject) => {
const tx = db.transaction('produkte', 'readwrite');
const range = IDBKeyRange.upperBound(10, true);
tx.objectStore('produkte').index('nachPreis').openCursor(range).onsuccess = (event) => {
const cursor = event.target.result;
if (!cursor) return;
// cursor.primaryKey passt zum Store, der hinter source.objectStore steht
console.log('Lösche', cursor.primaryKey, 'aus', cursor.source.objectStore.name);
cursor.delete();
cursor.continue();
};
tx.oncomplete = () => resolve();
tx.onerror = () => reject(tx.error);
});
// Wichtig · Fallstricke
- Schreibgeschützt: Wenn man
cursor.sourceetwas zuweist, wird das ignoriert (im Strict Mode gibt es einenTypeError). Um eine andere Quelle zu nutzen, muss man einen neuen Cursor öffnen. - Transaktion muss aktiv sein: Hebt man
sourceauf und ruft es später auf, etwa nach einemawaitoder in einemsetTimeout, gibt es einenTransactionInactiveError, denn IndexedDB-Transaktionen werden automatisch abgeschlossen. - Typ prüfen: Store und Index bieten unterschiedliche Eigenschaften (
objectStore,uniqueundmultiEntrygibt es nur am Index). Deshalb vorher mitinstanceof IDBIndexunterscheiden. - Kompatibilität: Wird von allen modernen Browsern unterstützt, auch in Web Workern. In Node.js gibt es IndexedDB nicht von Haus aus, dafür braucht man z. B.
fake-indexeddb.