IndexedDB â ÑÑо вÑÑÑÐ¾ÐµÐ½Ð½Ð°Ñ Ð±Ð°Ð·Ð° даннÑÑ
, более моÑнаÑ, Ñем localStorage.
- Ð¥ÑÐ°Ð½Ð¸Ñ Ð¿ÑакÑиÑеÑки лÑбÑе знаÑÐµÐ½Ð¸Ñ Ð¿Ð¾ клÑÑам, неÑколÑко Ñипов клÑÑей
- ÐоддеÑÐ¶Ð¸Ð²Ð°ÐµÑ ÑÑанзакÑии Ð´Ð»Ñ Ð½Ð°Ð´ÑжноÑÑи.
- ÐоддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð·Ð°Ð¿ÑоÑÑ Ð² диапазоне клÑÑей и индекÑÑ.
- ÐозволÑÐµÑ Ñ
ÑаниÑÑ Ð±Ð¾Ð»ÑÑе даннÑÑ
, Ñем
localStorage.
ÐÐ»Ñ ÑÑадиÑионнÑÑ ÐºÐ»Ð¸ÐµÐ½Ñ-ÑеÑвеÑнÑÑ Ð¿Ñиложений ÑÑа моÑноÑÑÑ Ð¾Ð±ÑÑно ÑÑезмеÑна. IndexedDB пÑедназнаÑена Ð´Ð»Ñ Ð¾ÑÑлайн пÑиложений, можно ÑовмеÑаÑÑ Ñ ServiceWorkers и дÑÑгими ÑÐµÑ Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñми.
ÐнÑеÑÑÐµÐ¹Ñ Ð´Ð»Ñ IndexedDB, опиÑаннÑй в ÑпеÑиÑикаÑии https://www.w3.org/TR/IndexedDB, оÑнован на ÑобÑÑиÑÑ .
ÐÑ Ñакже можем иÑполÑзоваÑÑ async/await Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Ð¾Ð±ÑÑÑки, коÑоÑÐ°Ñ Ð¾Ñнована на пÑомиÑаÑ
, напÑÐ¸Ð¼ÐµÑ https://github.com/jakearchibald/idb. ÐÑо оÑÐµÐ½Ñ Ñдобно, но обÑÑÑка не идеалÑна, она не Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾Ð»Ð½Ð¾ÑÑÑÑ Ð·Ð°Ð¼ÐµÐ½Ð¸ÑÑ ÑобÑÑиÑ. ÐоÑÑÐ¾Ð¼Ñ Ð¼Ñ Ð½Ð°ÑнÑм Ñ ÑобÑÑий, а заÑем, когда ÑазбеÑÑмÑÑ Ð² IndexedDB, ÑаÑÑмоÑÑим и обÑÑÑкÑ.
Ð¢ÐµÑ Ð½Ð¸ÑеÑки даннÑе обÑÑно Ñ ÑанÑÑÑÑ Ð² домаÑнем каÑалоге поÑеÑиÑÐµÐ»Ñ Ð²Ð¼ÐµÑÑе Ñ Ð½Ð°ÑÑÑойками бÑаÑзеÑа, ÑаÑÑиÑениÑми и Ñ.д.
У ÑазнÑÑ Ð±ÑаÑзеÑов и полÑзоваÑелей на ÑÑовне ÐС еÑÑÑ ÑÐ²Ð¾Ñ ÑобÑÑвенное незавиÑимое Ñ ÑанилиÑе.
ÐÑкÑÑÑÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
ÐÐ»Ñ Ð½Ð°Ñала ÑабоÑÑ Ñ IndexedDB нÑжно оÑкÑÑÑÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ .
СинÑакÑиÑ:
let openRequest = indexedDB.open(name, version);
nameâ название Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ , ÑÑÑока.versionâ веÑÑÐ¸Ñ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ , положиÑелÑное Ñелое ÑиÑло, по ÑмолÑаниÑ1(обÑÑÑнÑеÑÑÑ Ð½Ð¸Ð¶Ðµ).
У Ð½Ð°Ñ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¼Ð½Ð¾Ð¶ÐµÑÑво баз даннÑÑ Ñ ÑазлиÑнÑми именами, но вÑе они ÑÑÑеÑÑвÑÑÑ Ð² конÑекÑÑе ÑекÑÑего иÑÑоÑника (домен/пÑоÑокол/поÑÑ). РазнÑе ÑайÑÑ Ð½Ðµ могÑÑ Ð¿Ð¾Ð»ÑÑиÑÑ Ð´Ð¾ÑÑÑп к базам даннÑÑ Ð´ÑÑг дÑÑга.
ÐоÑле ÑÑого вÑзова необÑ
одимо назнаÑиÑÑ Ð¾Ð±ÑабоÑÑик ÑобÑÑий Ð´Ð»Ñ Ð¾Ð±ÑекÑа openRequest:
success: база даннÑÑ Ð³Ð¾Ñова к ÑабоÑе, гоÑов «обÑÐµÐºÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ Â»openRequest.result, его ÑледÑÐµÑ Ð¸ÑполÑзоваÑÑ Ð´Ð»Ñ Ð´Ð°Ð»ÑнейÑÐ¸Ñ Ð²Ñзовов.error: не ÑдалоÑÑ Ð¾ÑкÑÑÑÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ .upgradeneeded: база оÑкÑÑÑа, но ÐµÑ ÑÑ ÐµÐ¼Ð° ÑÑÑаÑела (Ñм. ниже).
IndexedDB Ð¸Ð¼ÐµÐµÑ Ð²ÑÑÑоеннÑй Ð¼ÐµÑ Ð°Ð½Ð¸Ð·Ð¼ «веÑÑиониÑÐ¾Ð²Ð°Ð½Ð¸Ñ ÑÑ ÐµÐ¼Ñ», коÑоÑÑй оÑÑÑÑÑÑвÑÐµÑ Ð² ÑеÑвеÑнÑÑ Ð±Ð°Ð·Ð°Ñ Ð´Ð°Ð½Ð½ÑÑ .
РоÑлиÑие Ð¾Ñ ÑеÑвеÑнÑÑ Ð±Ð°Ð· даннÑÑ , IndexedDB ÑабоÑÐ°ÐµÑ Ð½Ð° ÑÑоÑоне клиенÑа, в бÑаÑзеÑе, и Ñ Ð½Ð°Ñ Ð½ÐµÑ Ð¿ÑÑмого доÑÑÑпа к даннÑм. Ðо когда Ð¼Ñ Ð¿ÑбликÑем новÑÑ Ð²ÐµÑÑÐ¸Ñ Ð½Ð°Ñего пÑиложениÑ, возможно, нам понадобиÑÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð¸ÑÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ .
ÐÑли локалÑÐ½Ð°Ñ Ð²ÐµÑÑÐ¸Ñ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
менÑÑе, Ñем веÑÑиÑ, опÑеделÑÐ½Ð½Ð°Ñ Ð² open, Ñо ÑÑабоÑÐ°ÐµÑ ÑпеÑиалÑное ÑобÑÑие upgradeneeded, и Ð¼Ñ Ñможем ÑÑавниÑÑ Ð²ÐµÑÑии и обновиÑÑ ÑÑÑÑкÑÑÑÑ Ð´Ð°Ð½Ð½ÑÑ
по меÑе необÑ
одимоÑÑи.
ÐÑо ÑобÑÑие Ñакже ÑÑабоÑаеÑ, еÑли Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ ÐµÑÑ Ð½Ðµ ÑÑÑеÑÑвÑеÑ, Ñак ÑÑо в ÑÑом обÑабоÑÑике Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ вÑполниÑÑ Ð¸Ð½Ð¸ÑиализаÑиÑ.
ÐопÑÑÑим, Ð¼Ñ Ð¾Ð¿Ñбликовали пеÑвÑÑ Ð²ÐµÑÑÐ¸Ñ Ð½Ð°Ñего пÑиложениÑ.
ÐаÑем Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ оÑкÑÑÑÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
Ñ Ð²ÐµÑÑией 1 и вÑполниÑÑ Ð¸Ð½Ð¸ÑиализаÑÐ¸Ñ Ð² обÑабоÑÑике upgradeneeded Ð²Ð¾Ñ Ñак:
let openRequest = indexedDB.open("store", 1);
openRequest.onupgradeneeded = function() {
// ÑÑабаÑÑваеÑ, еÑли на клиенÑе Ð½ÐµÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
// ...вÑполниÑÑ Ð¸Ð½Ð¸ÑиализаÑиÑ...
};
openRequest.onerror = function() {
console.error("Error", openRequest.error);
};
openRequest.onsuccess = function() {
let db = openRequest.result;
// пÑодолжиÑÑ ÑабоÑÑ Ñ Ð±Ð°Ð·Ð¾Ð¹ даннÑÑ
, иÑполÑзÑÑ Ð¾Ð±ÑÐµÐºÑ db
};
ÐаÑем, позже, Ð¼Ñ Ð¿ÑбликÑем 2-Ñ Ð²ÐµÑÑиÑ.
ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ оÑкÑÑÑÑ ÐµÐ³Ð¾ Ñ Ð²ÐµÑÑией 2 и вÑполниÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ðµ ÑледÑÑÑим обÑазом:
let openRequest = indexedDB.open("store", 2);
openRequest.onupgradeneeded = function(event) {
// веÑÑÐ¸Ñ ÑÑÑеÑÑвÑÑÑей Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
менÑÑе 2 (или база даннÑÑ
не ÑÑÑеÑÑвÑеÑ)
let db = openRequest.result;
switch(event.oldVersion) { // ÑÑÑеÑÑвÑÑÑÐ°Ñ (ÑÑаÑаÑ) веÑÑÐ¸Ñ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
case 0:
// веÑÑÐ¸Ñ 0 ознаÑаеÑ, ÑÑо на клиенÑе Ð½ÐµÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
// вÑполниÑÑ Ð¸Ð½Ð¸ÑиализаÑиÑ
case 1:
// на клиенÑе веÑÑÐ¸Ñ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
1
// обновиÑÑ
}
};
Таким обÑазом, в openRequest.onupgradeneeded Ð¼Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»Ñем Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
. СкоÑо подÑобно Ñвидим, как ÑÑо делаеÑÑÑ. РпоÑле Ñого, как ÑÑÐ¾Ñ Ð¾Ð±ÑабоÑÑик завеÑÑиÑÑÑ Ð±ÐµÐ· оÑибок, ÑÑабоÑÐ°ÐµÑ openRequest.onsuccess.
ÐоÑле openRequest.onsuccess Ñ Ð½Ð°Ñ ÐµÑÑÑ Ð¾Ð±ÑÐµÐºÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
в openRequest.result, коÑоÑÑй Ð¼Ñ Ð±Ñдем иÑполÑзоваÑÑ Ð´Ð»Ñ Ð´Ð°Ð»ÑнейÑиÑ
опеÑаÑий.
УдалиÑÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ :
let deleteRequest = indexedDB.deleteDatabase(name)
// deleteRequest.onsuccess/onerror оÑÑÐ»ÐµÐ¶Ð¸Ð²Ð°ÐµÑ ÑезÑлÑÑаÑ
ЧÑо еÑли Ð¼Ñ Ð¿Ð¾Ð¿ÑобÑем оÑкÑÑÑÑ Ð±Ð°Ð·Ñ Ñ Ð±Ð¾Ð»ÐµÐµ низкой веÑÑией, Ñем ÑекÑÑаÑ? ÐапÑимеÑ, на клиенÑе база веÑÑии 3, а Ð¼Ñ Ð²ÑзÑваем open(...2).
ÐÐ¾Ð·Ð½Ð¸ÐºÐ½ÐµÑ Ð¾Ñибка, ÑÑабоÑÐ°ÐµÑ openRequest.onerror.
Такое Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑоизойÑи, еÑли поÑеÑиÑÐµÐ»Ñ Ð·Ð°Ð³ÑÑзил ÑÑÑаÑевÑий код, напÑимеÑ, из кеÑа пÑокÑи. Ðам ÑледÑÐµÑ Ð¿ÑовеÑиÑÑ db.version и пÑедложиÑÑ ÐµÐ¼Ñ Ð¿ÐµÑезагÑÑзиÑÑ ÑÑÑаниÑÑ. Ð Ñакже пÑовеÑиÑÑ Ð½Ð°Ñи кеÑиÑÑÑÑие заголовки, ÑбедиÑÑÑÑ, ÑÑо поÑеÑиÑÐµÐ»Ñ Ð½Ð¸ÐºÐ¾Ð³Ð´Ð° не полÑÑÐ¸Ñ ÑÑÑаÑевÑий код.
ÐÑоблема паÑаллелÑного обновлениÑ
Раз Ñж Ð¼Ñ Ð³Ð¾Ð²Ð¾Ñим пÑо веÑÑиониÑование, ÑаÑÑмоÑÑим ÑвÑзаннÑÑ Ñ ÑÑим неболÑÑÑÑ Ð¿ÑоблемÑ.
ÐопÑÑÑим:
- ÐоÑеÑиÑÐµÐ»Ñ Ð¾ÑкÑÑл Ð½Ð°Ñ ÑÐ°Ð¹Ñ Ð²Ð¾ вкладке бÑаÑзеÑа, Ñ Ð±Ð°Ð·Ð¾Ð¹ веÑÑии
1. - ÐаÑем Ð¼Ñ Ð²ÑпÑÑÑили обновление, Ñак ÑÑо Ð½Ð°Ñ ÐºÐ¾Ð´ обновилÑÑ.
- РзаÑем ÑÐ¾Ñ Ð¶Ðµ поÑеÑиÑÐµÐ»Ñ Ð¾ÑкÑÑл Ð½Ð°Ñ ÑÐ°Ð¹Ñ Ð² дÑÑгой вкладке.
Так ÑÑо еÑÑÑ Ð´Ð²Ðµ вкладки, на коÑоÑÑÑ
оÑкÑÑÑ Ð½Ð°Ñ ÑайÑ, но в одной оÑкÑÑÑо Ñоединение Ñ Ð±Ð°Ð·Ð¾Ð¹ веÑÑии 1, а дÑÑÐ³Ð°Ñ Ð¿ÑÑаеÑÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð¸ÑÑ Ð²ÐµÑÑÐ¸Ñ Ð±Ð°Ð·Ñ Ð² обÑабоÑÑике upgradeneeded.
ÐÑоблема заклÑÑаеÑÑÑ Ð² Ñом, ÑÑо база даннÑÑ Ð²Ñего одна на две вкладки, Ñак как ÑÑо один и ÑÐ¾Ñ Ð¶Ðµ ÑайÑ, один иÑÑоÑник. Рона не Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¾Ð´Ð½Ð¾Ð²Ñеменно веÑÑии 1 и 2. ЧÑÐ¾Ð±Ñ Ð¾Ð±Ð½Ð¾Ð²Ð¸ÑÑ Ð½Ð° веÑÑÐ¸Ñ 2, вÑе ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ðº веÑÑии 1 Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð·Ð°ÐºÑÑÑÑ.
ЧÑÐ¾Ð±Ñ ÑÑо можно бÑло оÑганизоваÑÑ, пÑи попÑÑке Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ð° обÑекÑе Ð±Ð°Ð·Ñ Ð²Ð¾Ð·Ð½Ð¸ÐºÐ°ÐµÑ ÑобÑÑие versionchange. Ðам нÑжно ÑлÑÑаÑÑ ÐµÐ³Ð¾ и закÑÑÑÑ Ñоединение к базе (а Ñакже, возможно, пÑедложиÑÑ Ð¿Ð¾Ð»ÑзоваÑÐµÐ»Ñ Ð¿ÐµÑезагÑÑзиÑÑ ÑÑÑаниÑÑ, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÑннÑй код).
ÐÑли Ð¼Ñ ÐµÐ³Ð¾ не закÑоем, Ñо вÑоÑое, новое Ñоединение бÑÐ´ÐµÑ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸Ñовано Ñ ÑобÑÑием blocked вмеÑÑо success.
Ðод, коÑоÑÑй ÑÑо делаеÑ:
let openRequest = indexedDB.open("store", 2);
openRequest.onupgradeneeded = ...;
openRequest.onerror = ...;
openRequest.onsuccess = function() {
let db = openRequest.result;
db.onversionchange = function() {
db.close();
alert("Ðаза даннÑÑ
ÑÑÑаÑела, пожалÑйÑÑа, пеÑезагÑÑзиÑе ÑÑÑаниÑÑ.")
};
// ...база даннÑÑ
гоÑова, иÑполÑзÑйÑе ее...
};
openRequest.onblocked = function() {
// ÑÑо ÑобÑÑие не должно ÑÑабаÑÑваÑÑ, еÑли Ð¼Ñ Ð¿ÑавилÑно обÑабаÑÑваем onversionchange
// ÑÑо ознаÑаеÑ, ÑÑо еÑÑÑ ÐµÑÑ Ð¾Ð´Ð½Ð¾ оÑкÑÑÑое Ñоединение Ñ Ñой же базой даннÑÑ
// и он не бÑл закÑÑÑ Ð¿Ð¾Ñле Ñого, как Ð´Ð»Ñ Ð½ÐµÐ³Ð¾ ÑÑабоÑал db.onversionchange
};
â¦ÐÑÑгими Ñловами, здеÑÑ Ð¼Ñ Ð´ÐµÐ»Ð°ÐµÐ¼ две веÑи:
- ÐбÑабоÑÑик
db.onversionchangeÑообÑÐ°ÐµÑ Ð½Ð°Ð¼ о попÑÑке паÑаллелÑного обновлениÑ, еÑли ÑекÑÑÐ°Ñ Ð²ÐµÑÑÐ¸Ñ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ ÑÑÑаÑела. - ÐбÑабоÑÑик
OpenRequest.onblockedÑообÑÐ°ÐµÑ Ð½Ð°Ð¼ об обÑаÑной ÑиÑÑаÑии: в дÑÑгом меÑÑе еÑÑÑ Ñоединение Ñ ÑÑÑаÑевÑей веÑÑией, и оно не закÑÑваеÑÑÑ, поÑÑÐ¾Ð¼Ñ Ð½Ð¾Ð²Ð¾Ðµ Ñоединение ÑÑÑановиÑÑ Ð½ÐµÐ²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾.
ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ более изÑÑно обÑаÑаÑÑÑÑ Ñ Ð²ÐµÑами в db.onversionchange, напÑÐ¸Ð¼ÐµÑ Ð¿ÑедлагаÑÑ Ð¿Ð¾ÑеÑиÑÐµÐ»Ñ ÑоÑ
ÑаниÑÑ Ð´Ð°Ð½Ð½Ñе до закÑÑÑÐ¸Ñ ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ð¸ Ñак далее.
Ðли алÑÑеÑнаÑивнÑм подÑ
одом бÑло Ð±Ñ Ð½Ðµ закÑÑваÑÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
в db.onversionchange, а вмеÑÑо ÑÑого иÑполÑзоваÑÑ Ð¾Ð±ÑабоÑÑик onblocked (на новой вкладке), ÑÑÐ¾Ð±Ñ Ð¿ÑедÑпÑедиÑÑ Ð¿Ð¾ÑеÑиÑелÑ, ÑÑо более Ð½Ð¾Ð²Ð°Ñ Ð²ÐµÑÑÐ¸Ñ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð·Ð°Ð³ÑÑжена, пока они не закÑоÑÑ Ð´ÑÑгие вкладки.
Такой конÑÐ»Ð¸ÐºÑ Ð¿Ñи обновлении пÑоиÑÑ
Ð¾Ð´Ð¸Ñ Ñедко, но Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ ÐºÐ°Ðº-Ñо его обÑабаÑÑваÑÑ, Ñ
оÑÑ Ð±Ñ Ð¿Ð¾ÑÑавиÑÑ Ð¾Ð±ÑабоÑÑик onblocked, ÑÑÐ¾Ð±Ñ Ð½Ð°Ñ ÑкÑÐ¸Ð¿Ñ Ð½Ðµ «ÑмиÑал» молÑа, ÑдивлÑÑ Ð¿Ð¾ÑеÑиÑелÑ.
Ð¥ÑанилиÑе обÑекÑов
ЧÑÐ¾Ð±Ñ ÑÐ¾Ñ ÑаниÑÑ ÑÑо-Ñо в IndexedDB, нам нÑжно Ñ ÑанилиÑе обÑекÑов.
Ð¥ÑанилиÑе обÑекÑов â ÑÑо оÑÐ½Ð¾Ð²Ð½Ð°Ñ ÐºÐ¾Ð½ÑепÑÐ¸Ñ IndexedDB. РдÑÑÐ³Ð¸Ñ Ð±Ð°Ð·Ð°Ñ Ð´Ð°Ð½Ð½ÑÑ ÑÑо «ÑаблиÑÑ» или «коллекÑии». ÐдеÑÑ Ñ ÑанÑÑÑÑ Ð´Ð°Ð½Ð½Ñе. Рбазе даннÑÑ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¼Ð½Ð¾Ð¶ÐµÑÑво Ñ ÑанилиÑ: одно Ð´Ð»Ñ Ð¿Ð¾Ð»ÑзоваÑелей, дÑÑгое Ð´Ð»Ñ ÑоваÑов и Ñак далее.
ÐеÑмоÑÑÑ Ð½Ð° Ñо, ÑÑо название â Â«Ñ ÑанилиÑе обÑекÑов», пÑимиÑÐ¸Ð²Ñ Ñоже могÑÑ Ñам Ñ ÑаниÑÑÑÑ.
ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ Ñ ÑаниÑÑ Ð¿Ð¾ÑÑи лÑбое знаÑение, в Ñом ÑиÑле ÑложнÑе обÑекÑÑ.
IndexedDB иÑполÑзÑÐµÑ ÑÑандаÑÑнÑй алгоÑиÑм ÑеÑиализаÑии Ð´Ð»Ñ ÐºÐ»Ð¾Ð½Ð¸ÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¸ Ñ
ÑÐ°Ð½ÐµÐ½Ð¸Ñ Ð¾Ð±ÑекÑа. ÐÑо как JSON.stringify, но более моÑнÑй, ÑпоÑобнÑй Ñ
ÑаниÑÑ Ð³Ð¾Ñаздо болÑÑе Ñипов даннÑÑ
.
ÐÑÐ¸Ð¼ÐµÑ Ð¾Ð±ÑекÑа, коÑоÑÑй нелÑÐ·Ñ ÑоÑ
ÑаниÑÑ: обÑÐµÐºÑ Ñ ÑиклиÑеÑкими ÑÑÑлками. Такие обÑекÑÑ Ð½Ðµ ÑеÑиализÑемÑ. JSON.stringify Ñакже вÑдаÑÑ Ð¾ÑÐ¸Ð±ÐºÑ Ð¿Ñи ÑеÑиализаÑии.
ÐÐ°Ð¶Ð´Ð¾Ð¼Ñ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð² Ñ ÑанилиÑе должен ÑооÑвеÑÑÑвоваÑÑ ÑникалÑнÑй клÑÑ.
ÐлÑÑ Ð´Ð¾Ð»Ð¶ÐµÐ½ бÑÑÑ Ð¾Ð´Ð½Ð¸Ð¼ из ÑледÑÑÑÐ¸Ñ Ñипов: number, date, string, binary или array. ÐÑо ÑникалÑнÑй иденÑиÑикаÑоÑ: по клÑÑÑ Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ иÑкаÑÑ/ÑдалÑÑÑ/обновлÑÑÑ Ð·Ð½Ð°ÑениÑ.
Ðак Ð¼Ñ Ð²Ð¸Ð´Ð¸Ð¼, можно ÑказаÑÑ ÐºÐ»ÑÑ Ð¿Ñи добавлении знаÑÐµÐ½Ð¸Ñ Ð² Ñ
ÑанилиÑе, аналогиÑно localStorage. Ðо когда Ð¼Ñ Ñ
Ñаним обÑекÑÑ, IndexedDB позволÑÐµÑ ÑÑÑановиÑÑ ÑвойÑÑво обÑекÑа в каÑеÑÑве клÑÑа, ÑÑо гоÑаздо Ñдобнее. Ðли Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ авÑомаÑиÑеÑки ÑгенеÑиÑоваÑÑ ÐºÐ»ÑÑи.
Ðо Ð´Ð»Ñ Ð½Ð°Ñала нÑжно ÑоздаÑÑ Ñ ÑанилиÑе.
СинÑакÑÐ¸Ñ Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ ÑанилиÑа обÑекÑов:
db.createObjectStore(name[, keyOptions]);
ÐбÑаÑиÑе внимание, ÑÑо опеÑаÑÐ¸Ñ ÑвлÑеÑÑÑ ÑинÑ
Ñонной, иÑполÑзование await не ÑÑебÑеÑÑÑ.
nameâ ÑÑо название Ñ ÑанилиÑа, напÑимеÑ"books"Ð´Ð»Ñ ÐºÐ½Ð¸Ð³,keyOptionsâ ÑÑо необÑзаÑелÑнÑй обÑÐµÐºÑ Ñ Ð¾Ð´Ð½Ð¸Ð¼ или двÑÐ¼Ñ ÑвойÑÑвами:keyPathâ пÑÑÑ Ðº ÑвойÑÑÐ²Ñ Ð¾Ð±ÑекÑа, коÑоÑое IndexedDB бÑÐ´ÐµÑ Ð¸ÑполÑзоваÑÑ Ð² каÑеÑÑве клÑÑа, напÑимеÑid.autoIncrementâ еÑлиtrue, Ñо клÑÑ Ð±ÑÐ´ÐµÑ ÑоÑмиÑоваÑÑÑÑ Ð°Ð²ÑомаÑиÑеÑки Ð´Ð»Ñ Ð½Ð¾Ð²ÑÑ Ð¾Ð±ÑекÑов, как поÑÑоÑнно ÑвелиÑиваÑÑееÑÑ ÑиÑло.
ÐÑли пÑи Ñоздании Ñ
ÑанилиÑа не ÑказаÑÑ keyOptions, Ñо нам поÑÑебÑеÑÑÑ Ñвно ÑказаÑÑ ÐºÐ»ÑÑ Ð¿Ð¾Ð·Ð¶Ðµ, пÑи ÑоÑ
Ñанении обÑекÑа.
ÐапÑимеÑ, ÑÑо Ñ
ÑанилиÑе обÑекÑов иÑполÑзÑÐµÑ ÑвойÑÑво id как клÑÑ:
db.createObjectStore('books', {keyPath: 'id'});
Ð¥ÑанилиÑе обÑекÑов можно ÑоздаваÑÑ/изменÑÑÑ ÑолÑко пÑи обновлении веÑÑии Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
в обÑабоÑÑике upgradeneeded.
ÐÑо ÑÐµÑ Ð½Ð¸ÑеÑкое огÑаниÑение. Ðне обÑабоÑÑика Ð¼Ñ Ñможем добавлÑÑÑ/ÑдалÑÑÑ/обновлÑÑÑ Ð´Ð°Ð½Ð½Ñе, но Ñ ÑанилиÑа обÑекÑов могÑÑ Ð±ÑÑÑ ÑозданÑ/ÑдаленÑ/Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ñ ÑолÑко во вÑÐµÐ¼Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÑÑии Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ .
ÐÐ»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÑÑии Ð±Ð°Ð·Ñ ÐµÑÑÑ Ð´Ð²Ð° оÑновнÑÑ Ð¿Ð¾Ð´Ñ Ð¾Ð´Ð°:
- ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ ÑеализоваÑÑ ÑÑнкÑии Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾ веÑÑиÑм: Ñ 1 на 2, Ñ 2 на 3 и Ñ.д. ÐоÑом в
upgradeneededÑÑавниÑÑ Ð²ÐµÑÑии (напÑимеÑ, бÑла 2, ÑейÑÐ°Ñ 4) и запÑÑÑиÑÑ Ð¾Ð¿ÐµÑаÑии Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ пÑомежÑÑоÑной веÑÑии (2 на 3, заÑем 3 на 4). - Ðли Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ взÑÑÑ ÑпиÑок ÑÑÑеÑÑвÑÑÑиÑ
Ñ
ÑÐ°Ð½Ð¸Ð»Ð¸Ñ Ð¾Ð±ÑекÑов, иÑполÑзÑÑ
db.objectStoreNames. ÐÑÐ¾Ñ Ð¾Ð±ÑÐµÐºÑ ÑвлÑеÑÑÑ DOMStringList, в нÑм еÑÑÑ Ð¼ÐµÑодcontains(name), иÑполÑзÑÑ ÐºÐ¾ÑоÑÑй можно пÑовеÑиÑÑ ÑÑÑеÑÑвование Ñ ÑанилиÑа. ÐоÑмоÑÑеÑÑ, какие Ñ ÑанилиÑа еÑÑÑ Ð¸ ÑоздаÑÑ Ñе, коÑоÑÑÑ Ð½ÐµÑ.
ÐÐ»Ñ Ð¿ÑоÑÑÑÑ Ð±Ð°Ð· даннÑÑ Ð²ÑоÑой Ð¿Ð¾Ð´Ñ Ð¾Ð´ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿ÑоÑе и пÑедпоÑÑиÑелÑнее.
ÐÐ¾Ñ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑаÑÐ¸Ñ Ð²ÑоÑого ÑпоÑоба:
let openRequest = indexedDB.open("db", 2);
// ÑоздаÑм Ñ
ÑанилиÑе обÑекÑов Ð´Ð»Ñ books, еÑли еÑÑ Ð½Ðµ ÑÑÑеÑÑвÑеÑ
openRequest.onupgradeneeded = function() {
let db = openRequest.result;
if (!db.objectStoreNames.contains('books')) { // еÑли Ñ
ÑанилиÑе "books" не ÑÑÑеÑÑвÑеÑ
db.createObjectStore('books', {keyPath: 'id'}); // ÑоздаÑм Ñ
ÑанилиÑе
}
};
ЧÑÐ¾Ð±Ñ ÑдалиÑÑ Ñ ÑанилиÑе обÑекÑов:
db.deleteObjectStore('books')
ТÑанзакÑии
ТеÑмин «ÑÑанзакÑиÑ» ÑвлÑеÑÑÑ Ð¾Ð±ÑеизвеÑÑнÑм, ÑÑанзакÑии иÑполÑзÑÑÑÑÑ Ð²Ð¾ Ð¼Ð½Ð¾Ð³Ð¸Ñ Ð²Ð¸Ð´Ð°Ñ Ð±Ð°Ð· даннÑÑ .
ТÑанзакÑÐ¸Ñ â ÑÑо гÑÑппа опеÑаÑий, коÑоÑÑе Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð¸Ð»Ð¸ вÑе вÑполненÑ, или вÑе не вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ñ (вÑÑ Ð¸Ð»Ð¸ ниÑего).
ÐапÑимеÑ, когда полÑзоваÑÐµÐ»Ñ ÑÑо-Ñо покÑпаеÑ, нам нÑжно:
- ÐÑÑеÑÑÑ Ð´ÐµÐ½Ñги Ñ ÐµÐ³Ð¾ ÑÑÑÑа.
- ÐÑпÑавиÑÑ ÐµÐ¼Ñ Ð¿Ð¾ÐºÑпкÑ.
ÐÑÐ´ÐµÑ Ð¾ÑÐµÐ½Ñ Ð¿Ð»Ð¾Ñ Ð¾, еÑли Ð¼Ñ ÑÑпеем завеÑÑиÑÑ Ð¿ÐµÑвÑÑ Ð¾Ð¿ÐµÑаÑиÑ, а заÑем ÑÑо-Ñо пойдÑÑ Ð½Ðµ Ñак, напÑÐ¸Ð¼ÐµÑ Ð¾ÑклÑÑÐ°Ñ ÑлекÑÑиÑеÑÑво, и Ð¼Ñ Ð½Ðµ Ñможем завеÑÑиÑÑ Ð²ÑоÑÑÑ Ð¾Ð¿ÐµÑаÑиÑ. Ðбе опеÑаÑии Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ ÑÑпеÑно завеÑÑÐµÐ½Ñ (покÑпка Ñделана, оÑлиÑно!) или Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ оÑмениÑÑ Ð¾Ð±Ðµ опеÑаÑии (в ÑÑом ÑлÑÑае полÑзоваÑÐµÐ»Ñ ÑÐ¾Ñ ÑÐ°Ð½Ð¸Ñ Ñвои денÑги и Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾Ð¿ÑÑаÑÑÑÑ ÐºÑпиÑÑ ÐµÑÑ Ñаз).
ТÑанзакÑии гаÑанÑиÑÑÑÑ ÑÑо.
ÐÑе опеÑаÑии Ñ Ð´Ð°Ð½Ð½Ñми в IndexedDB могÑÑ Ð±ÑÑÑ ÑÐ´ÐµÐ»Ð°Ð½Ñ ÑолÑко внÑÑÑи ÑÑанзакÑий.
ÐÐ»Ñ Ð½Ð°Ñала ÑÑанзакÑии:
db.transaction(store[, type]);
storeâ ÑÑо название Ñ ÑанилиÑа, к коÑоÑÐ¾Ð¼Ñ ÑÑанзакÑÐ¸Ñ Ð¿Ð¾Ð»ÑÑÐ¸Ñ Ð´Ð¾ÑÑÑп, напÑимеÑ,"books". ÐÐ¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¼Ð°ÑÑивом названий, еÑли нам нÑжно пÑедоÑÑавиÑÑ Ð´Ð¾ÑÑÑп к неÑколÑким Ñ ÑанилиÑам.typeâ Ñип ÑÑанзакÑии, один из:readonlyâ ÑолÑко ÑÑение, по ÑмолÑаниÑ.readwriteâ ÑолÑко ÑÑение и запиÑÑ Ð´Ð°Ð½Ð½ÑÑ , Ñоздание/Ñдаление ÑÐ°Ð¼Ð¸Ñ Ñ ÑÐ°Ð½Ð¸Ð»Ð¸Ñ Ð¾Ð±ÑекÑов недоÑÑÑпно.
ÐÑÑÑ ÐµÑÑ Ð¾Ð´Ð¸Ð½ Ñип ÑÑанзакÑий: versionchange. Такие ÑÑанзакÑии могÑÑ Ð´ÐµÐ»Ð°ÑÑ Ð»ÑбÑе опеÑаÑии, но Ð¼Ñ Ð½Ðµ можем ÑоздаÑÑ Ð¸Ñ
вÑÑÑнÑÑ. IndexedDB авÑомаÑиÑеÑки ÑоздаÑÑ ÑÑанзакÑÐ¸Ñ Ñипа versionchange, когда оÑкÑÑÐ²Ð°ÐµÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
, Ð´Ð»Ñ Ð¾Ð±ÑабоÑÑика upgradeneeded. ÐÐ¾Ñ Ð¿Ð¾ÑÐµÐ¼Ñ ÑÑо единÑÑвенное меÑÑо, где Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ обновлÑÑÑ ÑÑÑÑкÑÑÑÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
, ÑоздаваÑÑ/ÑдалÑÑÑ Ñ
ÑанилиÑа обÑекÑов.
ÐÑоизводиÑелÑноÑÑÑ ÑвлÑеÑÑÑ Ð¿ÑиÑиной, поÑÐµÐ¼Ñ ÑÑанзакÑии необÑ
одимо помеÑаÑÑ ÐºÐ°Ðº readonly или readwrite.
ÐеÑколÑко readonly ÑÑанзакÑий могÑÑ Ð¾Ð´Ð½Ð¾Ð²Ñеменно ÑабоÑаÑÑ Ñ Ð¾Ð´Ð½Ð¸Ð¼ и Ñем же Ñ ÑанилиÑем обÑекÑов, а readwrite ÑÑанзакÑий â не могÑÑ. ТÑанзакÑии Ñипа readwrite «блокиÑÑÑÑ» Ñ ÑанилиÑе Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи. СледÑÑÑÐ°Ñ ÑÐ°ÐºÐ°Ñ ÑÑанзакÑÐ¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° дождаÑÑÑÑ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿ÑедÑдÑÑей, пеÑед Ñем как полÑÑÐ¸Ñ Ð´Ð¾ÑÑÑп к ÑÐ¾Ð¼Ñ Ð¶Ðµ ÑÐ°Ð¼Ð¾Ð¼Ñ Ñ ÑанилиÑÑ.
ÐоÑле Ñого, как ÑÑанзакÑÐ¸Ñ Ð±ÑÐ´ÐµÑ Ñоздана, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ добавиÑÑ ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð² Ñ ÑанилиÑе, Ð²Ð¾Ñ Ñак:
let transaction = db.transaction("books", "readwrite"); // (1)
// полÑÑиÑÑ Ñ
ÑанилиÑе обÑекÑов Ð´Ð»Ñ ÑабоÑÑ Ñ Ð½Ð¸Ð¼
let books = transaction.objectStore("books"); // (2)
let book = {
id: 'js',
price: 10,
created: new Date()
};
let request = books.add(book); // (3)
request.onsuccess = function() { // (4)
console.log("Ðнига добавлена в Ñ
ÑанилиÑе", request.result);
};
request.onerror = function() {
console.log("ÐÑибка", request.error);
};
ÐÑ Ñделали ÑеÑÑÑе Ñага:
- СоздаÑÑ ÑÑанзакÑÐ¸Ñ Ð¸ ÑказаÑÑ Ð²Ñе Ñ
ÑанилиÑа, к коÑоÑÑм необÑ
одим доÑÑÑп, ÑÑÑока
(1). - ÐолÑÑиÑÑ Ñ
ÑанилиÑе обÑекÑов, иÑполÑзÑÑ
transaction.objectStore(name), ÑÑÑока(2). - ÐÑполниÑÑ Ð·Ð°Ð¿ÑÐ¾Ñ Ð½Ð° добавление ÑлеменÑа в Ñ
ÑанилиÑе обÑекÑов
books.add(book), ÑÑÑока(3). - â¦ÐбÑабоÑаÑÑ ÑезÑлÑÑÐ°Ñ Ð·Ð°Ð¿ÑоÑа
(4), заÑем Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ вÑполниÑÑ Ð´ÑÑгие запÑоÑÑ Ð¸ Ñак далее.
Ð¥ÑанилиÑа обÑекÑов поддеÑживаÑÑ Ð´Ð²Ð° меÑода Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñений:
-
put(value, [key]) ÐобавлÑÐµÑ Ð·Ð½Ð°Ñение
valueв Ñ ÑанилиÑе. ÐлÑÑkeyÐ½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ ÑказаÑÑ, еÑли пÑи Ñоздании Ñ ÑанилиÑа обÑекÑов не бÑло Ñказано ÑвойÑÑвоkeyPathилиautoIncrement. ÐÑли Ñже еÑÑÑ Ð·Ð½Ð°Ñение Ñ Ñаким же клÑÑом, Ñо оно бÑÐ´ÐµÑ Ð·Ð°Ð¼ÐµÐ½ÐµÐ½Ð¾. -
add(value, [key]) То же, ÑÑо
put, но еÑли Ñже ÑÑÑеÑÑвÑÐµÑ Ð·Ð½Ð°Ñение Ñ Ñаким клÑÑом, Ñо запÑÐ¾Ñ Ð½Ðµ вÑполниÑÑÑ, бÑÐ´ÐµÑ ÑгенеÑиÑована оÑибка Ñ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸ÐµÐ¼"ConstraintError".
ÐналогиÑно оÑкÑÑÑÐ¸Ñ Ð±Ð°Ð·Ñ, Ð¼Ñ Ð¾ÑпÑавлÑем запÑоÑ: books.add(book) и поÑле ожидаем ÑобÑÑÐ¸Ñ success/error.
request.resultдлÑaddÑвлÑеÑÑÑ ÐºÐ»ÑÑом нового обÑекÑа.- ÐÑибка наÑ
одиÑÑÑ Ð²
request.error(еÑли еÑÑÑ).
ÐвÑомаÑиÑеÑÐºÐ°Ñ ÑикÑаÑÐ¸Ñ ÑÑанзакÑий
РпÑимеÑе вÑÑе Ð¼Ñ Ð·Ð°Ð¿ÑÑÑили ÑÑанзакÑÐ¸Ñ Ð¸ вÑполнили запÑÐ¾Ñ add. Ðо, как говоÑилоÑÑ Ñанее, ÑÑанзакÑÐ¸Ñ Ð¼Ð¾Ð¶ÐµÑ Ð²ÐºÐ»ÑÑаÑÑ Ð² ÑÐµÐ±Ñ Ð½ÐµÑколÑко запÑоÑов, коÑоÑÑе вÑе вмеÑÑе Ð´Ð¾Ð»Ð¶Ð½Ñ Ð»Ð¸Ð±Ð¾ ÑÑпеÑно завеÑÑиÑÑÑÑ, либо неÑ. Ðак нам законÑиÑÑ ÑÑанзакÑиÑ, обознаÑиÑÑ, ÑÑо болÑÑе запÑоÑов в ней не бÑдеÑ?
ÐоÑоÑкий оÑвеÑ: ÑÑого не ÑÑебÑеÑÑÑ.
Ð ÑледÑÑÑей 3.0 веÑÑии ÑпеÑиÑикаÑии, веÑоÑÑно, бÑÐ´ÐµÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ Ð²ÑÑÑнÑÑ Ð·Ð°Ð²ÐµÑÑиÑÑ ÑÑанзакÑиÑ, но ÑейÑаÑ, в веÑÑии 2.0, Ñакой возможноÑÑи неÑ.
Ðогда вÑе запÑоÑÑ Ð·Ð°Ð²ÐµÑÑÐµÐ½Ñ Ð¸ оÑеÑÐµÐ´Ñ Ð¼Ð¸ÐºÑÐ¾Ð·Ð°Ð´Ð°Ñ Ð¿ÑÑÑа, Ñогда ÑÑанзакÑÐ¸Ñ Ð·Ð°Ð²ÐµÑÑиÑÑÑ Ð°Ð²ÑомаÑиÑеÑки.
Ðак пÑавило, ÑÑо ознаÑаеÑ, ÑÑо ÑÑанзакÑÐ¸Ñ Ð°Ð²ÑомаÑиÑеÑки завеÑÑаеÑÑÑ, когда вÑполнилиÑÑ Ð²Ñе ÐµÑ Ð·Ð°Ð¿ÑоÑÑ Ð¸ завеÑÑилÑÑ ÑекÑÑий код.
Таким обÑазом, в пÑиведÑнном вÑÑе пÑимеÑе не ÑÑебÑеÑÑÑ Ð½Ð¸ÐºÐ°ÐºÐ¾Ð³Ð¾ ÑпеÑиалÑного вÑзова, ÑÑÐ¾Ð±Ñ Ð·Ð°Ð²ÐµÑÑиÑÑ ÑÑанзакÑиÑ.
Такое авÑозавеÑÑение ÑÑанзакÑий Ð¸Ð¼ÐµÐµÑ Ð²Ð°Ð¶Ð½Ñй побоÑнÑй ÑÑÑекÑ. ÐÑ Ð½Ðµ можем вÑÑавиÑÑ Ð°ÑинÑ
ÑоннÑÑ Ð¾Ð¿ÐµÑаÑиÑ, ÑакÑÑ ÐºÐ°Ðº fetch или setTimeout в ÑеÑÐµÐ´Ð¸Ð½Ñ ÑÑанзакÑии. IndexedDB никак не заÑÑÐ°Ð²Ð¸Ñ ÑÑанзакÑÐ¸Ñ Â«Ð²Ð¸ÑеÑÑ» и ждаÑÑ Ð¸Ñ
вÑполнениÑ.
РпÑиведÑнном ниже коде в запÑоÑе request2 в ÑÑÑоке Ñ (*) бÑÐ´ÐµÑ Ð¾Ñибка, поÑÐ¾Ð¼Ñ ÑÑо ÑÑанзакÑÐ¸Ñ Ñже завеÑÑена, болÑÑе нелÑÐ·Ñ Ð²ÑполниÑÑ Ð² ней запÑоÑ:
let request1 = books.add(book);
request1.onsuccess = function() {
fetch('/').then(response => {
let request2 = books.add(anotherBook); // (*)
request2.onerror = function() {
console.log(request2.error.name); // TransactionInactiveError
};
});
};
ÐÑÑ Ð¿Ð¾ÑомÑ, ÑÑо fetch ÑвлÑеÑÑÑ Ð°ÑинÑ
Ñонной опеÑаÑией, макÑозадаÑей. ТÑанзакÑии завеÑÑаÑÑÑÑ ÑанÑÑе, Ñем бÑаÑÐ·ÐµÑ Ð¿ÑиÑÑÑÐ¿Ð°ÐµÑ Ðº вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¼Ð°ÐºÑозадаÑ.
ÐвÑоÑÑ ÑпеÑиÑикаÑии IndexedDB из ÑообÑажений пÑоизводиÑелÑноÑÑи ÑÑиÑаÑÑ, ÑÑо ÑÑанзакÑии Ð´Ð¾Ð»Ð¶Ð½Ñ Ð·Ð°Ð²ÐµÑÑаÑÑÑÑ Ð±ÑÑÑÑо.
Ð ÑаÑÑноÑÑи, readwrite ÑÑанзакÑии «блокиÑÑÑÑ» Ñ
ÑанилиÑа Ð¾Ñ Ð·Ð°Ð¿Ð¸Ñи. Таким обÑазом, еÑли одна ÑаÑÑÑ Ð¿ÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¸Ð½Ð¸ÑииÑÑÐµÑ readwrite ÑÑанзакÑÐ¸Ñ Ð² Ñ
ÑанилиÑе обÑекÑов books, Ñо дÑÑÐ³Ð°Ñ ÑаÑÑÑ Ð¿ÑиложениÑ, коÑоÑÐ°Ñ Ñ
оÑÐµÑ ÑделаÑÑ Ñо же Ñамое, должна ждаÑÑ: Ð½Ð¾Ð²Ð°Ñ ÑÑанзакÑÐ¸Ñ Â«Ð·Ð°Ð²Ð¸ÑаеÑ» до завеÑÑÐµÐ½Ð¸Ñ Ð¿ÐµÑвой. ÐÑо Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑивеÑÑи к ÑÑÑаннÑм задеÑжкам, еÑли ÑÑанзакÑии ÑлиÑком долго вÑполнÑÑÑÑÑ.
ЧÑо же делаÑÑ?
РпÑиведÑнном вÑÑе пÑимеÑе Ð¼Ñ Ð¼Ð¾Ð³Ð»Ð¸ Ð±Ñ Ð·Ð°Ð¿ÑÑÑиÑÑ Ð½Ð¾Ð²ÑÑ ÑÑанзакÑÐ¸Ñ db.transaction пеÑед новÑм запÑоÑом (*).
Ðо еÑÑ Ð»ÑÑÑе вÑполнÑÑÑ Ð¾Ð¿ÐµÑаÑии вмеÑÑе, в ÑÐ°Ð¼ÐºÐ°Ñ Ð¾Ð´Ð½Ð¾Ð¹ ÑÑанзакÑии: оÑделиÑÑ ÑÑанзакÑии IndexedDB Ð¾Ñ Ð´ÑÑÐ³Ð¸Ñ Ð°ÑÐ¸Ð½Ñ ÑоннÑÑ Ð¾Ð¿ÐµÑаÑий.
СнаÑала Ñделаем fetch, подгоÑовим даннÑе, еÑли нÑжно, заÑем Ñоздадим ÑÑанзакÑÐ¸Ñ Ð¸ вÑполним вÑе запÑоÑÑ Ðº базе даннÑÑ
.
ЧÑÐ¾Ð±Ñ Ð¿Ð¾Ð¹Ð¼Ð°ÑÑ Ð¼Ð¾Ð¼ÐµÐ½Ñ ÑÑпеÑного вÑполнениÑ, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ повеÑиÑÑ Ð¾Ð±ÑабоÑÑик на ÑобÑÑие transaction.oncomplete:
let transaction = db.transaction("books", "readwrite");
// ...вÑполниÑÑ Ð¾Ð¿ÐµÑаÑии...
transaction.oncomplete = function() {
console.log("ТÑанзакÑÐ¸Ñ Ð²Ñполнена");
};
ТолÑко complete гаÑанÑиÑÑеÑ, ÑÑо ÑÑанзакÑÐ¸Ñ ÑоÑ
Ñанена Ñеликом. Ðо оÑделÑноÑÑи запÑоÑÑ Ð¼Ð¾Ð³ÑÑ Ð²ÑполниÑÑÑÑ, но пÑи ÑиналÑной запиÑи ÑÑо-Ñо Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾Ð¹Ñи не Ñак (оÑибка ввода-вÑвода, пÑоблема Ñ Ð´Ð¸Ñком, напÑимеÑ).
ЧÑÐ¾Ð±Ñ Ð²ÑÑÑнÑÑ Ð¾ÑмениÑÑ ÑÑанзакÑиÑ, вÑполниÑе:
transaction.abort();
ÐÑо оÑÐ¼ÐµÐ½Ð¸Ñ Ð²Ñе изменениÑ, ÑделаннÑе запÑоÑами в ÑÑанзакÑии, и ÑгенеÑиÑÑÐµÑ ÑобÑÑие transaction.onabort.
ÐбÑабоÑка оÑибок
ÐапÑоÑÑ Ð½Ð° запиÑÑ Ð¼Ð¾Ð³ÑÑ Ð²ÑполниÑÑÑÑ Ð½ÐµÑдаÑно.
ÐÑ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð³Ð¾ÑÐ¾Ð²Ñ Ðº ÑÑомÑ, не ÑолÑко из-за возможнÑÑ Ð¾Ñибок на наÑей ÑÑоÑоне, но и по пÑиÑинам, коÑоÑÑе не ÑвÑÐ·Ð°Ð½Ñ Ñ ÑÑанзакÑией. ÐапÑимеÑ, ÑÐ°Ð·Ð¼ÐµÑ Ñ ÑанилиÑа Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿ÑевÑÑен. Ð Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð³Ð¾ÑÐ¾Ð²Ñ Ð¾Ð±ÑабоÑаÑÑ ÑакÑÑ ÑиÑÑаÑиÑ.
ÐÑи оÑибке в запÑоÑе ÑооÑвеÑÑÑвÑÑÑÐ°Ñ ÑÑанзакÑÐ¸Ñ Ð¾ÑменÑеÑÑÑ Ð¿Ð¾Ð»Ð½Ð¾ÑÑÑÑ, вклÑÑÐ°Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ, ÑделаннÑе дÑÑгими ÐµÑ Ð·Ð°Ð¿ÑоÑами.
ÐÑли Ð¼Ñ Ñ
оÑим пÑодолжиÑÑ ÑÑанзакÑÐ¸Ñ (напÑимеÑ, попÑобоваÑÑ Ð´ÑÑгой запÑÐ¾Ñ Ð±ÐµÐ· оÑÐ¼ÐµÐ½Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹), ÑÑо Ñакже возможно. ÐÐ»Ñ ÑÑого в обÑабоÑÑике request.onerror ÑледÑÐµÑ Ð²ÑзваÑÑ event.preventDefault().
РпÑимеÑе ниже Ð½Ð¾Ð²Ð°Ñ ÐºÐ½Ð¸Ð³Ð° добавлÑеÑÑÑ Ñ Ñем же клÑÑом (id), ÑÑо и ÑÑÑеÑÑвÑÑÑаÑ. ÐеÑод store.add генеÑиÑÑÐµÑ Ð² ÑÑом ÑлÑÑае оÑÐ¸Ð±ÐºÑ "ConstraintError". ÐÑ Ð¾Ð±ÑабаÑÑваем ÐµÑ Ð±ÐµÐ· оÑÐ¼ÐµÐ½Ñ ÑÑанзакÑии:
let transaction = db.transaction("books", "readwrite");
let book = { id: 'js', price: 10 };
let request = transaction.objectStore("books").add(book);
request.onerror = function(event) {
// ConstraintError Ð²Ð¾Ð·Ð½Ð¸ÐºÐ°ÐµÑ Ð¿Ñи попÑÑке добавиÑÑ Ð¾Ð±ÑÐµÐºÑ Ñ ÐºÐ»ÑÑом, коÑоÑÑй Ñже ÑÑÑеÑÑвÑеÑ
if (request.error.name == "ConstraintError") {
console.log("Ðнига Ñ Ñаким id Ñже ÑÑÑеÑÑвÑеÑ"); // обÑабаÑÑваем оÑибкÑ
event.preventDefault(); // пÑедоÑвÑаÑаем оÑÐ¼ÐµÐ½Ñ ÑÑанзакÑии
// ...можно попÑобоваÑÑ Ð¸ÑполÑзоваÑÑ Ð´ÑÑгой клÑÑ...
} else {
// неизвеÑÑÐ½Ð°Ñ Ð¾Ñибка
// ÑÑанзакÑÐ¸Ñ Ð±ÑÐ´ÐµÑ Ð¾Ñменена
}
};
transaction.onabort = function() {
console.log("ÐÑибка", transaction.error);
};
ÐелегиÑование ÑобÑÑий
ÐÑÐ¶Ð½Ñ Ð»Ð¸ обÑабоÑÑики onerror/onsuccess Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ запÑоÑа? Ðе вÑегда. ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ Ð´ÐµÐ»ÐµÐ³Ð¸Ñование ÑобÑÑий.
СобÑÑÐ¸Ñ IndexedDB вÑплÑваÑÑ: запÑÐ¾Ñ â ÑÑанзакÑÐ¸Ñ â база даннÑÑ
.
ÐÑе ÑобÑÑÐ¸Ñ ÑвлÑÑÑÑÑ DOM-ÑобÑÑиÑми Ñ Ñазами пеÑÐµÑ Ð²Ð°Ñа и вÑплÑÑиÑ, но обÑÑно иÑполÑзÑеÑÑÑ ÑолÑко вÑплÑÑие.
ÐоÑÑÐ¾Ð¼Ñ Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ пеÑеÑ
ваÑиÑÑ Ð²Ñе оÑибки, иÑполÑзÑÑ Ð¾Ð±ÑабоÑÑик db.onerror, Ð´Ð»Ñ Ð¾Ð¿Ð¾Ð²ÐµÑÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑзоваÑÐµÐ»Ñ Ð¸Ð»Ð¸ дÑÑгиÑ
Ñелей:
db.onerror = function(event) {
let request = event.target; // запÑоÑ, в коÑоÑом пÑоизоÑла оÑибка
console.log("ÐÑибка", request.error);
};
â¦Ð еÑли Ð¼Ñ Ð¿Ð¾Ð»Ð½Ð¾ÑÑÑÑ Ð¾Ð±ÑабоÑали оÑибкÑ? Ð ÑÑом ÑлÑÑае Ð¼Ñ Ð½Ðµ Ñ Ð¾Ñим ÑообÑаÑÑ Ð¾Ð± ÑÑом.
ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ оÑÑановиÑÑ Ð²ÑплÑÑие и, ÑледоваÑелÑно, db.onerror, иÑполÑзÑÑ event.stopPropagation() в request.onerror.
request.onerror = function(event) {
if (request.error.name == "ConstraintError") {
console.log("Ðнига Ñ Ñаким id Ñже ÑÑÑеÑÑвÑеÑ"); // обÑабаÑÑваем оÑибкÑ
event.preventDefault(); // пÑедоÑвÑаÑаем оÑÐ¼ÐµÐ½Ñ ÑÑанзакÑии
event.stopPropagation(); // пÑедоÑвÑаÑаем вÑплÑÑие оÑибки
} else {
// ниÑего не делаем
// ÑÑанзакÑÐ¸Ñ Ð±ÑÐ´ÐµÑ Ð¾Ñменена
// Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ обÑабоÑаÑÑ Ð¾ÑÐ¸Ð±ÐºÑ Ð² transaction.onabort
}
};
ÐоиÑк по клÑÑам
ÐÑÑÑ Ð´Ð²Ð° оÑновнÑÑ Ð²Ð¸Ð´Ð° поиÑка в Ñ ÑанилиÑе обÑекÑов:
- Ðо знаÑÐµÐ½Ð¸Ñ ÐºÐ»ÑÑа или Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ñ ÐºÐ»ÑÑей. РнаÑем Ñ
ÑанилиÑе «books» ÑÑо бÑÐ´ÐµÑ Ð·Ð½Ð°Ñение или диапазон знаÑений
book.id. - С помоÑÑÑ Ð´ÑÑгого Ð¿Ð¾Ð»Ñ Ð¾Ð±ÑекÑа, напÑимеÑ
book.price. ÐÐ»Ñ ÑÑого поÑÑебовалаÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑÐ½Ð°Ñ ÑÑÑÑкÑÑÑа даннÑÑ , полÑÑивÑÐ°Ñ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ðµ «index».
Ðо клÑÑÑ
СнаÑала давайÑе ÑазбеÑÑмÑÑ Ñ Ð¿ÐµÑвÑм Ñипом поиÑка: по клÑÑÑ.
ÐеÑÐ¾Ð´Ñ Ð¿Ð¾Ð¸Ñка поддеÑживаÑÑ Ð»Ð¸Ð±Ð¾ ÑоÑнÑе клÑÑи, либо Ñак назÑваемÑе «запÑоÑÑ Ñ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð¾Ð¼Â» â IDBKeyRange обÑекÑÑ, коÑоÑÑе задаÑÑ Â«Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½ клÑÑей».
ÐÐ¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ñ ÑоздаÑÑÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÑледÑÑÑÐ¸Ñ Ð²Ñзовов:
IDBKeyRange.lowerBound(lower, [open])ознаÑаеÑ:>lower(илиâ¥lower, еÑлиopenÑÑо true)IDBKeyRange.upperBound(upper, [open])ознаÑаеÑ:<upper(илиâ¤upper, еÑлиopenÑÑо true)IDBKeyRange.bound(lower, upper, [lowerOpen], [upperOpen])ознаÑаеÑ: междÑlowerиupper, вклÑÑиÑелÑно, еÑли ÑооÑвеÑÑÑвÑÑÑийopenÑавенtrue.IDBKeyRange.only(key)â диапазон, коÑоÑÑй ÑоÑÑÐ¾Ð¸Ñ ÑолÑко из одного клÑÑаkey, Ñедко иÑполÑзÑеÑÑÑ.
ÐÑÐµÐ½Ñ ÑкоÑо Ð¼Ñ Ñвидим пÑакÑиÑеÑкие пÑимеÑÑ Ð¸Ñ Ð¸ÑполÑзованиÑ.
ÐÐ»Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÑакÑиÑеÑкого поиÑка ÑÑÑеÑÑвÑÑÑ ÑледÑÑÑие меÑодÑ. Ðни пÑинимаÑÑ Ð°ÑгÑÐ¼ÐµÐ½Ñ query, коÑоÑÑй Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð»Ð¸Ð±Ð¾ ÑоÑнÑм клÑÑом, либо диапазоном клÑÑей:
store.get(query)â поиÑк пеÑвого знаÑÐµÐ½Ð¸Ñ Ð¿Ð¾ клÑÑÑ Ð¸Ð»Ð¸ по диапазонÑ.store.getAll([query], [count])â поиÑк вÑÐµÑ Ð·Ð½Ð°Ñений, можно огÑаниÑиÑÑ, пеÑедавcount.store.getKey(query)â поиÑк пеÑвого клÑÑа, коÑоÑÑй ÑдовлеÑвоÑÑÐµÑ Ð·Ð°Ð¿ÑоÑÑ, обÑÑно пеÑедаÑÑÑÑ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½.store.getAllKeys([query], [count])â поиÑк вÑÐµÑ ÐºÐ»ÑÑей, коÑоÑÑе ÑдовлеÑвоÑÑÑÑ Ð·Ð°Ð¿ÑоÑÑ, обÑÑно пеÑедаÑÑÑÑ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½, возможно огÑаниÑиÑÑ Ð¿Ð¾Ð¸Ñк, пеÑедавcount.store.count([query])â полÑÑиÑÑ Ð¾Ð±Ñее колиÑеÑÑво клÑÑей, коÑоÑÑе ÑдовлеÑвоÑÑÑÑ Ð·Ð°Ð¿ÑоÑÑ, обÑÑно пеÑедаÑÑÑÑ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½.
ÐапÑимеÑ, в Ñ
ÑанилиÑе Ñ Ð½Ð°Ñ ÐµÑÑÑ Ð¼Ð½Ð¾Ð¶ÐµÑÑво книг. ÐомниÑе, поле id ÑвлÑеÑÑÑ ÐºÐ»ÑÑом, поÑÑÐ¾Ð¼Ñ Ð²Ñе ÑÑи меÑÐ¾Ð´Ñ Ð¼Ð¾Ð³ÑÑ Ð¸ÑкаÑÑ Ð¿Ð¾ клÑÑÑ id.
ÐÑимеÑÑ Ð·Ð°Ð¿ÑоÑов:
// полÑÑиÑÑ Ð¾Ð´Ð½Ñ ÐºÐ½Ð¸Ð³Ñ
books.get('js')
// полÑÑиÑÑ ÐºÐ½Ð¸Ð³Ð¸ Ñ 'css' <= id <= 'html'
books.getAll(IDBKeyRange.bound('css', 'html'))
// полÑÑиÑÑ ÐºÐ½Ð¸Ð³Ð¸ Ñ id < 'html'
books.getAll(IDBKeyRange.upperBound('html', true))
// полÑÑиÑÑ Ð²Ñе книги
books.getAll()
// полÑÑиÑÑ Ð²Ñе клÑÑи, гдe id > 'js'
books.getAllKeys(IDBKeyRange.lowerBound('js', true))
Ð¥ÑанилиÑе обÑекÑов внÑÑÑенне ÑоÑÑиÑÑÐµÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð¿Ð¾ клÑÑам.
ÐоÑÑÐ¾Ð¼Ñ Ð·Ð°Ð¿ÑоÑÑ, коÑоÑÑе возвÑаÑаÑÑ Ð¼Ð½Ð¾Ð³Ð¾ знаÑений, вÑегда возвÑаÑаÑÑ Ð¸Ñ Ð² поÑÑдке ÑоÑÑиÑовки по клÑÑÑ.
ÐоиÑк по индекÑиÑÐ¾Ð²Ð°Ð½Ð½Ð¾Ð¼Ñ Ð¿Ð¾Ð»Ñ
ÐÐ»Ñ Ð¿Ð¾Ð¸Ñка по дÑÑгим полÑм обÑекÑа нам нÑжно ÑоздаÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑÑ ÑÑÑÑкÑÑÑÑ Ð´Ð°Ð½Ð½ÑÑ , назÑваемÑÑ Â«Ð¸Ð½Ð´ÐµÐºÑ» (index).
ÐÐ½Ð´ÐµÐºÑ ÑвлÑеÑÑÑ Â«ÑаÑÑиÑением» к Ñ ÑанилиÑÑ, коÑоÑое оÑÑÐ»ÐµÐ¶Ð¸Ð²Ð°ÐµÑ Ð´Ð°Ð½Ð½Ð¾Ðµ поле обÑекÑа. ÐÐ»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ знаÑÐµÐ½Ð¸Ñ ÑÑого Ð¿Ð¾Ð»Ñ Ñ ÑаниÑÑÑ ÑпиÑок клÑÑей Ð´Ð»Ñ Ð¾Ð±ÑекÑов, коÑоÑÑе имеÑÑ ÑÑо знаÑение. Ðиже бÑÐ´ÐµÑ Ð±Ð¾Ð»ÐµÐµ подÑÐ¾Ð±Ð½Ð°Ñ ÐºÐ°ÑÑина.
СинÑакÑиÑ:
objectStore.createIndex(name, keyPath, [options]);
nameâ название индекÑа,keyPathâ пÑÑÑ Ðº Ð¿Ð¾Ð»Ñ Ð¾Ð±ÑекÑа, коÑоÑое Ð¸Ð½Ð´ÐµÐºÑ Ð´Ð¾Ð»Ð¶ÐµÐ½ оÑÑлеживаÑÑ (Ð¼Ñ ÑобиÑаемÑÑ ÑделаÑÑ Ð¿Ð¾Ð¸Ñк по ÑÑÐ¾Ð¼Ñ Ð¿Ð¾Ð»Ñ),optionâ необÑзаÑелÑнÑй обÑÐµÐºÑ Ñо ÑвойÑÑвами:uniqueâ еÑли true, Ñогда в Ñ ÑанилиÑе Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ ÑолÑко один обÑÐµÐºÑ Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ñм знаÑением вkeyPath. ÐÑли Ð¼Ñ Ð¿Ð¾Ð¿ÑÑаемÑÑ Ð´Ð¾Ð±Ð°Ð²Ð¸ÑÑ Ð´ÑбликаÑ, Ñо Ð¸Ð½Ð´ÐµÐºÑ ÑгенеÑиÑÑÐµÑ Ð¾ÑибкÑ.multiEntryâ иÑполÑзÑеÑÑÑ ÑолÑко, еÑлиkeyPathÑвлÑеÑÑÑ Ð¼Ð°ÑÑивом. Ð ÑÑом ÑлÑÑае, по ÑмолÑаниÑ, Ð¸Ð½Ð´ÐµÐºÑ Ð¾Ð±ÑабаÑÑÐ²Ð°ÐµÑ Ð²ÐµÑÑ Ð¼Ð°ÑÑив как клÑÑ. Ðо еÑли Ð¼Ñ Ñкажем true вmultiEntry, Ñогда Ð¸Ð½Ð´ÐµÐºÑ Ð±ÑÐ´ÐµÑ Ñ ÑаниÑÑ ÑпиÑок обÑекÑов Ñ ÑанилиÑа Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ знаÑÐµÐ½Ð¸Ñ Ð² ÑÑом маÑÑиве. Таким обÑазом, ÑлеменÑÑ Ð¼Ð°ÑÑива ÑÑановÑÑÑÑ ÐºÐ»ÑÑами индекÑа.
РнаÑем пÑимеÑе Ð¼Ñ Ñ
Ñаним книги Ñ ÐºÐ»ÑÑом id.
ÐопÑÑÑим, Ð¼Ñ Ñ
оÑим ÑделаÑÑ Ð¿Ð¾Ð¸Ñк по Ð¿Ð¾Ð»Ñ price.
СнаÑала нам нÑжно ÑоздаÑÑ Ð¸Ð½Ð´ÐµÐºÑ. ÐндекÑÑ Ð´Ð¾Ð»Ð¶Ð½Ñ ÑоздаваÑÑÑÑ Ð² upgradeneeded, как и Ñ
ÑанилиÑе обÑекÑов:
openRequest.onupgradeneeded = function() {
// Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ ÑоздаÑÑ Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð´ÐµÑÑ, в versionchange ÑÑанзакÑии
let books = db.createObjectStore('books', {keyPath: 'id'});
let index = books.createIndex('price_idx', 'price');
};
- ÐÐ½Ð´ÐµÐºÑ Ð±ÑÐ´ÐµÑ Ð¾ÑÑлеживаÑÑ Ð¿Ð¾Ð»Ðµ
price. - Ðоле price не ÑникалÑное, Ñ Ð½Ð°Ñ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð½ÐµÑколÑко книг Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ð¾Ð¹ Ñеной, поÑÑÐ¾Ð¼Ñ Ð¼Ñ Ð½Ðµ ÑÑÑанавливаем опÑиÑ
unique. - Ðоле price не ÑвлÑеÑÑÑ Ð¼Ð°ÑÑивом, поÑÑÐ¾Ð¼Ñ Ñлаг
multiEntryне пÑименим.
ÐÑедÑÑавим, ÑÑо в наÑем books еÑÑÑ 4 книги. ÐÐ¾Ñ ÐºÐ°ÑÑинка, коÑоÑÐ°Ñ Ð¿Ð¾ÐºÐ°Ð·ÑваеÑ, ÑÑо Ñакое «индекÑ».
Ðак Ñже говоÑилоÑÑ, Ð¸Ð½Ð´ÐµÐºÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ знаÑÐµÐ½Ð¸Ñ price (вÑоÑой аÑгÑменÑ) Ñ
ÑÐ°Ð½Ð¸Ñ ÑпиÑок клÑÑей, имеÑÑиÑ
ÑÑÑ ÑенÑ.
ÐндекÑÑ Ð°Ð²ÑомаÑиÑеÑки обновлÑÑÑÑÑ, нам не нÑжно об ÑÑом забоÑиÑÑÑÑ.
СейÑаÑ, когда Ð¼Ñ Ñ Ð¾Ñим найÑи обÑÐµÐºÑ Ð¿Ð¾ Ñене, Ð¼Ñ Ð¿ÑоÑÑо пÑименÑем Ñе же меÑÐ¾Ð´Ñ Ð¿Ð¾Ð¸Ñка к индекÑÑ:
let transaction = db.transaction("books"); // readonly
let books = transaction.objectStore("books");
let priceIndex = books.index("price_idx");
let request = priceIndex.getAll(10);
request.onsuccess = function() {
if (request.result !== undefined) {
console.log("Ðниги", request.result); // маÑÑив книг Ñ Ñеной 10
} else {
console.log("ÐÐµÑ ÑакиÑ
книг");
}
};
ÐÑ Ñакже можем иÑполÑзоваÑÑ IDBKeyRange, ÑÑÐ¾Ð±Ñ ÑоздаÑÑ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½ и найÑи деÑÑвÑе/доÑогие книги:
// найдÑм книги, где Ñена < 5
let request = priceIndex.getAll(IDBKeyRange.upperBound(5));
ÐндекÑÑ Ð²Ð½ÑÑÑенне оÑÑоÑÑиÑÐ¾Ð²Ð°Ð½Ñ Ð¿Ð¾ Ð¿Ð¾Ð»Ñ Ð¾ÑÑлеживаемого обÑекÑа, в наÑем ÑлÑÑае по price. ÐоÑÑÐ¾Ð¼Ñ ÑезÑлÑÑÐ°Ñ Ð¿Ð¾Ð¸Ñка бÑÐ´ÐµÑ Ñже оÑÑоÑÑиÑованнÑй по Ð¿Ð¾Ð»Ñ price.
Удаление из Ñ ÑанилиÑа
ÐеÑод delete ÑдалÑÐµÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð¿Ð¾ запÑоÑÑ, ÑоÑÐ¼Ð°Ñ Ð²Ñзова Ñакой же как в getAll:
delete(query)â пÑÐ¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ Ñдаление ÑооÑвеÑÑÑвÑÑÑÐ¸Ñ Ð·Ð°Ð¿ÑоÑÑ Ð·Ð½Ð°Ñений.
ÐапÑимеÑ:
// ÑдалиÑÑ ÐºÐ½Ð¸Ð³Ñ Ñ id='js'
books.delete('js');
ÐÑли нам нÑжно ÑдалиÑÑ ÐºÐ½Ð¸Ð³Ð¸, оÑновÑваÑÑÑ Ð½Ð° Ñене или на лÑбом дÑÑгом поле, ÑнаÑала нам надо найÑи клÑÑ Ð² индекÑе, а заÑем вÑполниÑÑ delete:
// найдÑм клÑÑ, где Ñена = 5
let request = priceIndex.getKey(5);
request.onsuccess = function() {
let id = request.result;
let deleteRequest = books.delete(id);
};
ЧÑÐ¾Ð±Ñ ÑдалиÑÑ Ð²ÑÑ:
books.clear(); // оÑиÑаем Ñ
ÑанилиÑе.
ÐÑÑÑоÑÑ
Такие меÑÐ¾Ð´Ñ ÐºÐ°Ðº getAll/getAllKeys возвÑаÑаÑÑ Ð¼Ð°ÑÑив клÑÑей/знаÑений.
Ðо Ñ
ÑанилиÑе обÑекÑов Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¾Ð³ÑомнÑм, болÑÑе, Ñем доÑÑÑпно памÑÑи. Тогда меÑод getAll веÑнÑÑ Ð¾ÑÐ¸Ð±ÐºÑ Ð¿Ñи попÑÑке полÑÑиÑÑ Ð²Ñе запиÑи в маÑÑиве.
ЧÑо делаÑÑ?
ÐÑÑÑоÑÑ Ð¿ÑедоÑÑавлÑÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑи Ð´Ð»Ñ ÑабоÑÑ Ð² ÑÐ°ÐºÐ¸Ñ ÑиÑÑаÑиÑÑ .
ÐбÑÐµÐºÑ cursor идÑÑ Ð¿Ð¾ Ñ ÑанилиÑÑ Ð¾Ð±ÑекÑов Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ñм запÑоÑом (query) и возвÑаÑÐ°ÐµÑ Ð¿Ð°ÑÑ ÐºÐ»ÑÑ/знаÑение по оÑеÑеди, а не вÑе ÑÑазÑ. ÐÑо позволÑÐµÑ ÑкономиÑÑ Ð¿Ð°Ð¼ÑÑÑ.
Так как Ñ ÑанилиÑе обÑекÑов внÑÑÑенне оÑÑоÑÑиÑовано по клÑÑÑ, кÑÑÑÐ¾Ñ Ð¿ÑÐ¾Ñ Ð¾Ð´Ð¸Ñ Ð¿Ð¾ Ñ ÑанилиÑÑ Ð² поÑÑдке Ñ ÑÐ°Ð½ÐµÐ½Ð¸Ñ ÐºÐ»ÑÑей (по возÑаÑÑÐ°Ð½Ð¸Ñ Ð¿Ð¾ ÑмолÑаниÑ).
СинÑакÑиÑ:
// как getAll, но Ñ Ð¸ÑполÑзованием кÑÑÑоÑа:
let request = store.openCursor([query], [direction]);
// ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ ÐºÐ»ÑÑи, не знаÑÐµÐ½Ð¸Ñ (как getAllKeys): store.openKeyCursor
queryклÑÑ Ð¸Ð»Ð¸ диапазон клÑÑей, как длÑgetAll.directionнеобÑзаÑелÑнÑй аÑгÑменÑ, доÑÑÑпнÑе знаÑениÑ:"next"â по ÑмолÑаниÑ, кÑÑÑÐ¾Ñ Ð±ÑÐ´ÐµÑ Ð¿ÑÐ¾Ñ Ð¾Ð´Ð¸ÑÑ Ð¾Ñ Ñамого маленÑкого клÑÑа к болÑÑемÑ."prev"â обÑаÑнÑй поÑÑдок: Ð¾Ñ Ñамого болÑÑого клÑÑа к менÑÑемÑ."nextunique","prevunique"â Ñо же Ñамое, но кÑÑÑÐ¾Ñ Ð¿ÑопÑÑÐºÐ°ÐµÑ Ð·Ð°Ð¿Ð¸Ñи Ñ Ñем же клÑÑом, ÑÑо Ñже бÑл (ÑолÑко Ð´Ð»Ñ ÐºÑÑÑоÑов по индекÑам, напÑимеÑ, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÐºÐ½Ð¸Ð³ Ñ price=5, бÑÐ´ÐµÑ Ð²Ð¾Ð·Ð²ÑаÑена ÑолÑко пеÑваÑ).
ÐÑновнÑм оÑлиÑием кÑÑÑоÑа ÑвлÑеÑÑÑ Ñо, ÑÑо request.onsuccess генеÑиÑÑеÑÑÑ Ð¼Ð½Ð¾Ð³Ð¾ÐºÑаÑно: один Ñаз Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ÑезÑлÑÑаÑа.
ÐÐ¾Ñ Ð¿ÑÐ¸Ð¼ÐµÑ Ñого, как иÑполÑзоваÑÑ ÐºÑÑÑоÑ:
let transaction = db.transaction("books");
let books = transaction.objectStore("books");
let request = books.openCursor();
// вÑзÑваеÑÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ найденной кÑÑÑоÑом книги
request.onsuccess = function() {
let cursor = request.result;
if (cursor) {
let key = cursor.key; // клÑÑ ÐºÐ½Ð¸Ð³Ð¸ (поле id)
let value = cursor.value; // обÑÐµÐºÑ ÐºÐ½Ð¸Ð³Ð¸
console.log(key, value);
cursor.continue();
} else {
console.log("Ðниг болÑÑе неÑ");
}
};
ÐÑновнÑе меÑÐ¾Ð´Ñ ÐºÑÑÑоÑа:
advance(count)â пÑодвинÑÑÑ ÐºÑÑÑÐ¾Ñ Ð½Ð°countпозиÑий, пÑопÑÑÑив знаÑениÑ.continue([key])â пÑодвинÑÑÑ ÐºÑÑÑÐ¾Ñ Ðº ÑледÑÑÑÐµÐ¼Ñ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð² диапазоне ÑооÑвеÑÑÑÐ²Ð¸Ñ (или до позиÑии ÑÑÐ°Ð·Ñ Ð¿Ð¾Ñле клÑÑа key, еÑли Ñказан).
ÐезавиÑимо Ð¾Ñ Ñого, еÑÑÑ Ð»Ð¸ еÑÑ Ð·Ð½Ð°ÑениÑ, ÑооÑвеÑÑÑвÑÑÑие кÑÑÑоÑÑ Ð¸Ð»Ð¸ Ð½ÐµÑ â вÑзÑваеÑÑÑ onsuccess, заÑем вresult Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ полÑÑиÑÑ ÐºÑÑÑоÑ, ÑказÑваÑÑий на ÑледÑÑÑÑÑ Ð·Ð°Ð¿Ð¸ÑÑ Ð¸Ð»Ð¸ ÑавнÑй undefined.
РпÑиведÑнном вÑÑе пÑимеÑе кÑÑÑÐ¾Ñ Ð±Ñл Ñоздан Ð´Ð»Ñ Ñ ÑанилиÑа обÑекÑов.
Ðо Ð¼Ñ Ñакже можем ÑоздаÑÑ ÐºÑÑÑÐ¾Ñ Ð´Ð»Ñ Ð¸Ð½Ð´ÐµÐºÑов. Ðак Ð¼Ñ Ð¿Ð¾Ð¼Ð½Ð¸Ð¼, индекÑÑ Ð¿Ð¾Ð·Ð²Ð¾Ð»ÑÑÑ Ð¸ÑкаÑÑ Ð¿Ð¾ Ð¿Ð¾Ð»Ñ Ð¾Ð±ÑекÑа. ÐÑÑÑоÑÑ Ð´Ð»Ñ Ð¸Ð½Ð´ÐµÐºÑов ÑабоÑаÑÑ Ñак же, как Ð´Ð»Ñ Ñ ÑÐ°Ð½Ð¸Ð»Ð¸Ñ Ð¾Ð±ÑекÑов â они позволÑÑÑ ÑкономиÑÑ Ð¿Ð°Ð¼ÑÑÑ, возвÑаÑÐ°Ñ Ð¾Ð´Ð½Ð¾ знаÑение в единиÑÑ Ð²Ñемени.
ÐÐ»Ñ ÐºÑÑÑоÑов по индекÑам cursor.key ÑвлÑеÑÑÑ ÐºÐ»ÑÑом индекÑа (напÑÐ¸Ð¼ÐµÑ price), нам ÑледÑÐµÑ Ð¸ÑполÑзоваÑÑ ÑвойÑÑво cursor.primaryKey как клÑÑ Ð¾Ð±ÑекÑа:
let request = priceIdx.openCursor(IDBKeyRange.upperBound(5));
// вÑзÑваеÑÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ запиÑи
request.onsuccess = function() {
let cursor = request.result;
if (cursor) {
let key = cursor.primaryKey; // ÑледÑÑÑий клÑÑ Ð² Ñ
ÑанилиÑе обÑекÑов (поле id)
let value = cursor.value; // ÑледÑÑÑее знаÑение в Ñ
ÑанилиÑе обÑекÑов (обÑÐµÐºÑ "книга")
let keyIndex = cursor.key; // ÑледÑÑÑий клÑÑ Ð¸Ð½Ð´ÐµÐºÑа (price)
console.log(key, value);
cursor.continue();
} else {
console.log("Ðниг болÑÑе неÑ");
}
};
ÐбÑÑÑка Ð´Ð»Ñ Ð¿ÑомиÑов
ÐобавлÑÑÑ Ðº ÐºÐ°Ð¶Ð´Ð¾Ð¼Ñ Ð·Ð°Ð¿ÑоÑÑ onsuccess/onerror немного гÑомоздко. ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ ÑделаÑÑ Ð½Ð°ÑÑ Ð¶Ð¸Ð·Ð½Ñ Ð¿ÑоÑе, иÑполÑзÑÑ Ð´ÐµÐ»ÐµÐ³Ð¸Ñование ÑобÑÑий, напÑимеÑ, ÑÑÑановиÑÑ Ð¾Ð±ÑабоÑÑики на вÑе ÑÑанзакÑии, но иÑполÑзоваÑÑ async/await намного Ñдобнее.
ÐавайÑе далее в главе иÑполÑзоваÑÑ Ð½ÐµÐ±Ð¾Ð»ÑÑÑÑ Ð¾Ð±ÑÑÑÐºÑ Ð½Ð°Ð´ пÑомиÑами https://github.com/jakearchibald/idb. Ðна ÑоздаÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑнÑй idb обÑÐµÐºÑ Ñ Ð¿ÑомиÑиÑиÑиÑованнÑми IndexedDB меÑодами.
Тогда вмеÑÑо onsuccess/onerror Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ пиÑаÑÑ Ð¿ÑимеÑно Ñак:
let db = await idb.openDb('store', 1, db => {
if (db.oldVersion == 0) {
// вÑполнÑем иниÑиализаÑиÑ
db.createObjectStore('books', {keyPath: 'id'});
}
});
let transaction = db.transaction('books', 'readwrite');
let books = transaction.objectStore('books');
try {
await books.add(...);
await books.add(...);
await transaction.complete;
console.log('ÑоÑ
Ñанено');
} catch(err) {
console.log('оÑибка', err.message);
}
ТепеÑÑ Ñ Ð½Ð°Ñ ÐºÑаÑивÑй «плоÑкий аÑинÑ
ÑоннÑй» код и, конеÑно, бÑÐ´ÐµÑ ÑабоÑаÑÑ try..catch.
ÐбÑабоÑка оÑибок
ÐÑли Ð¼Ñ Ð½Ðµ пеÑеÑ
ваÑим оÑибкÑ, Ñо она «вÑвалиÑÑÑ» наÑÑжÑ, ввеÑÑ
по ÑÑÐµÐºÑ Ð²Ñзовов, до ближайÑего внеÑнего try..catch.
ÐеобÑабоÑÐ°Ð½Ð½Ð°Ñ Ð¾Ñибка ÑÑановиÑÑÑ ÑобÑÑием «unhandled promise rejection» в обÑекÑе window.
ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ обÑабоÑаÑÑ Ñакие оÑибки Ð²Ð¾Ñ Ñак:
window.addEventListener('unhandledrejection', event => {
let request = event.target; // обÑÐµÐºÑ Ð·Ð°Ð¿ÑоÑа IndexedDB
let error = event.reason; // ÐеобÑабоÑаннÑй обÑÐµÐºÑ Ð¾Ñибки, как request.error
...ÑообÑиÑÑ Ð¾Ð± оÑибке...
});
ÐодводнÑй каменÑ: «Inactive transaction»
Ðак Ð¼Ñ Ñже знаем, ÑÑанзакÑии авÑомаÑиÑеÑки завеÑÑаÑÑÑÑ, как ÑолÑко бÑаÑÐ·ÐµÑ Ð·Ð°Ð²ÐµÑÑÐ°ÐµÑ ÑабоÑÑ Ñ ÑекÑÑим кодом и макÑозадаÑÑ. ÐоÑÑомÑ, еÑли Ð¼Ñ Ð¿Ð¾Ð¼ÐµÑÑим макÑозадаÑÑ Ð½Ð°Ð¿Ð¾Ð´Ð¾Ð±Ð¸Ðµ fetch в ÑеÑÐµÐ´Ð¸Ð½Ñ ÑÑанзакÑии, ÑÑанзакÑÐ¸Ñ Ð½Ðµ бÑÐ´ÐµÑ Ð¾Ð¶Ð¸Ð´Ð°ÑÑ ÐµÑ Ð·Ð°Ð²ÐµÑÑениÑ. ÐÑоизойдÑÑ Ð°Ð²ÑозавеÑÑение ÑÑанзакÑии. ÐоÑÑÐ¾Ð¼Ñ Ð¿Ñи ÑледÑÑÑем запÑоÑе Ð²Ð¾Ð·Ð½Ð¸ÐºÐ½ÐµÑ Ð¾Ñибка.
ÐÐ»Ñ Ð¿ÑомиÑиÑиÑиÑÑÑÑей обÑÑÑки и async/await поведение Ñакое же.
ÐÐ¾Ñ Ð¿ÑÐ¸Ð¼ÐµÑ fetch в ÑеÑедине ÑÑанзакÑии:
let transaction = db.transaction("inventory", "readwrite");
let inventory = transaction.objectStore("inventory");
await inventory.add({ id: 'js', price: 10, created: new Date() });
await fetch(...); // (*)
await inventory.add({ id: 'js', price: 10, created: new Date() }); // ÐÑибка
СледÑÑÑий inventory.add поÑле fetch (*) не ÑÑабоÑаеÑ, ÑгенеÑиÑÑеÑÑÑ Ð¾Ñибка «inactive transaction», поÑÐ¾Ð¼Ñ ÑÑо ÑÑанзакÑÐ¸Ñ Ñже завеÑÑена и закÑÑÑа к ÑÑÐ¾Ð¼Ñ Ð²Ñемени.
РеÑение Ñакое же, как пÑи ÑабоÑе Ñ Ð¾Ð±ÑÑнÑм IndexedDB: либо ÑоздаÑÑ Ð½Ð¾Ð²ÑÑ ÑÑанзакÑиÑ, либо ÑазделиÑÑ Ð·Ð°Ð´Ð°ÑÑ Ð½Ð° ÑаÑÑи.
- ÐодгоÑовиÑÑ Ð´Ð°Ð½Ð½Ñе и полÑÑиÑÑ Ð²ÑÑ, ÑÑо Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾.
- ÐаÑем ÑÐ¾Ñ ÑаниÑÑ Ð² Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ .
ÐолÑÑение вÑÑÑоеннÑÑ Ð¾Ð±ÑекÑов
ÐнÑÑÑенне обÑÑÑка вÑполнÑÐµÑ Ð²ÑÑÑоеннÑе IndexedDB запÑоÑÑ, добавлÑÑ Ðº ним onerror/onsuccess, и возвÑаÑÐ°ÐµÑ Ð¿ÑомиÑÑ, коÑоÑÑе оÑклонÑÑÑÑÑ Ð¸Ð»Ð¸ вÑполнÑÑÑÑÑ Ñ Ð¿ÐµÑеданнÑм ÑезÑлÑÑаÑом.
ÐÑо ÑабоÑÐ°ÐµÑ Ð² болÑÑинÑÑве ÑлÑÑаев. ÐÑимеÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ ÑвидеÑÑ Ð½Ð° ÑÑÑаниÑе библиоÑеки https://github.com/jakearchibald/idb.
РнекоÑоÑÑÑ
ÑедкиÑ
ÑлÑÑаÑÑ
, когда нам нÑжен оÑигиналÑнÑй обÑÐµÐºÑ request, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ полÑÑиÑÑ Ðº Ð½ÐµÐ¼Ñ Ð´Ð¾ÑÑÑп, иÑполÑзÑÑ ÑвойÑÑво promise.request:
let promise = books.add(book); // полÑÑаем пÑÐ¾Ð¼Ð¸Ñ (без await, не ждÑм ÑезÑлÑÑаÑа)
let request = promise.request; // вÑÑÑоеннÑй обÑÐµÐºÑ Ð·Ð°Ð¿ÑоÑа
let transaction = request.transaction; // вÑÑÑоеннÑй обÑÐµÐºÑ ÑÑанзакÑии
// ...ÑабоÑаем Ñ IndexedDB...
let result = await promise; // еÑли еÑÑ Ð½Ñжно
ÐÑого
IndexedDB можно ÑаÑÑмаÑÑиваÑÑ ÐºÐ°Ðº «localStorage на ÑÑеÑÐ¾Ð¸Ð´Ð°Ñ Â». ÐÑо пÑоÑÑÐ°Ñ Ð±Ð°Ð·Ð° даннÑÑ Ñипа клÑÑ-знаÑение, доÑÑаÑоÑно моÑÐ½Ð°Ñ Ð´Ð»Ñ Ð¾ÑÑлайн пÑиложений, но пÑоÑÑÐ°Ñ Ð² иÑполÑзовании.
ÐÑÑÑим ÑÑководÑÑвом ÑвлÑеÑÑÑ ÑпеÑиÑикаÑиÑ, ÑекÑÑÐ°Ñ Ð²ÐµÑÑÐ¸Ñ 2.0, но Ñакже поддеÑживаÑÑÑÑ Ð½ÐµÑколÑко меÑодов из 3.0 (не Ñак много оÑлиÑий) веÑÑии.
ÐÑполÑзование можно опиÑаÑÑ Ð² неÑколÑÐºÐ¸Ñ ÑÑÐ°Ð·Ð°Ñ :
- ÐодклÑÑиÑÑ Ð¾Ð±ÑÑÑÐºÑ Ð½Ð°Ð´ пÑомиÑами, напÑÐ¸Ð¼ÐµÑ idb.
- ÐÑкÑÑÑÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
:
idb.openDb(name, version, onupgradeneeded)- СоздайÑе Ñ
ÑанилиÑа обÑекÑов и индекÑÑ Ð² обÑабоÑÑике
onupgradeneededили вÑполниÑе обновление веÑÑии, еÑли ÑÑо Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾
- СоздайÑе Ñ
ÑанилиÑа обÑекÑов и индекÑÑ Ð² обÑабоÑÑике
- ÐÐ»Ñ Ð·Ð°Ð¿ÑоÑов:
- СоздаÑÑ ÑÑанзакÑиÑ
db.transaction('books')(можно ÑказаÑÑ readwrite, еÑли надо). - ÐолÑÑиÑÑ Ñ
ÑанилиÑе обÑекÑов
transaction.objectStore('books').
- СоздаÑÑ ÑÑанзакÑиÑ
- ÐаÑем Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка по клÑÑÑ Ð²ÑзÑваем меÑÐ¾Ð´Ñ Ð½ÐµÐ¿Ð¾ÑÑедÑÑвенно Ñ Ñ
ÑанилиÑа обÑекÑов.
- ÐÐ»Ñ Ð¿Ð¾Ð¸Ñка по лÑÐ±Ð¾Ð¼Ñ Ð¿Ð¾Ð»Ñ Ð¾Ð±ÑекÑа ÑоздайÑе индекÑ.
- ÐÑли даннÑе не помеÑаÑÑÑÑ Ð² памÑÑи, Ñо иÑполÑзÑйÑе кÑÑÑоÑ.
Ðемо-пÑиложение:
<!doctype html>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/idb.min.js"></script>
<button onclick="addBook()">ÐобавиÑÑ ÐºÐ½Ð¸Ð³Ñ</button>
<button onclick="clearBooks()">ÐÑиÑÑиÑÑ Ñ
ÑанилиÑе</button>
<p>СпиÑок книг:</p>
<ul id="listElem"></ul>
<script>
let db;
init();
async function init() {
db = await idb.openDb('booksDb', 1, db => {
db.createObjectStore('books', {keyPath: 'name'});
});
list();
}
async function list() {
let tx = db.transaction('books');
let bookStore = tx.objectStore('books');
let books = await bookStore.getAll();
if (books.length) {
listElem.innerHTML = books.map(book => `<li>
название: ${book.name}, Ñена: ${book.price}
</li>`).join('');
} else {
listElem.innerHTML = '<li>Ðниг пока неÑ. ÐожалÑйÑÑа, добавÑÑе книги.</li>'
}
}
async function clearBooks() {
let tx = db.transaction('books', 'readwrite');
await tx.objectStore('books').clear();
await list();
}
async function addBook() {
let name = prompt("Ðазвание книги");
let price = +prompt("Цена книги");
let tx = db.transaction('books', 'readwrite');
try {
await tx.objectStore('books').add({name, price});
await list();
} catch(err) {
if (err.name == 'ConstraintError') {
alert("Ð¢Ð°ÐºÐ°Ñ ÐºÐ½Ð¸Ð³Ð° Ñже ÑÑÑеÑÑвÑеÑ");
await addBook();
} else {
throw err;
}
}
}
window.addEventListener('unhandledrejection', event => {
alert("ÐÑибка: " + event.reason.message);
});
</script>
ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)