2012-05-06 11 views
15

İndeksliDB'nin nesne deposuna ~ 35000 nesne kaydetmek istiyorum. Eklemek için aşağıdaki kodu kullanıyorum.Büyük miktarlarda IndexedDB'nin nesne deposu bloklarına ekleme UI

AddListings = function (x2j_list_new, callback) { 
    var transaction = db.transaction(["listings"], IDBTransaction.READ_WRITE); 
    var count = 0; 
    transaction.oncomplete = function (event) { 
     if (callback) { 
      console.log('x2jShowListing Added ' + count + '/' + x2j_list_new.length); 
       callback([count, x2j_list_new.length]); 
      } 
    }; 
    transaction.onerror = function (e) { 
     console.log("myError: ", e); 
     if (callback) { 
      callback(false); 
     } 
    }; 
    var store = transaction.objectStore("listings"); 

    $.each(x2j_list_new, function (index0, item0) { 
     var request = store.put(item0); 
     request.onsuccess = function (event) { 
      count++; 
      // event.target.result 
      }; 
     }); 
    });   
}; 

yukarıdaki kod çalışıyor ama döngüye ve ~ 35.000 nesneleri üzerinde ekleme ~ 200 saniye boyunca tepkisiz UI yapar. WebWorkers'ı kullanabileceğimi düşündüm, ancak IndexedDB WebWorkers içinde kullanılamaz. Toplu yerleştirmenin bir yolunu bulmaya çalıştım, bir tane bulamadım. Kullanıcı arayüzünü engellemeden büyük miktarda nesnenin nasıl ekleneceği hakkında herhangi bir fikir var mı?

+1

(http://stackoverflow.com/questions/ 8495687/bölünmüş-dizi-in-chunks) 500 ve [setInterval] kullanarak (http://www.kryogenix.org/days/2009/07/03/not-blocking-the-ui-in-tight-javascript- döngü için). Şimdi UI öncekinden biraz daha iyi tepki veriyor. – surya

cevap

28

'dan biraz daha iyi tepki veriyor, ancak doğru yoldasınız, ancak tarayıcının bir tanesini bitirme şansı olmadan önce 35.000 nesne saklamasını istiyorsunuz. İşte bir istek sonraki başlangıç ​​(ama aynı işlem kullanılarak) bitmesini uyumsuz bekler kod: şimdi [parçalarını] içinde dizi bölme am için

openRequest = window.indexedDB.open("MyDatabase", 1); 
    openRequest.onerror = function(event) { 
     console.error(event); 
    }; 
    openRequest.onsuccess = function (event) { 
     var db = openRequest.result; 
     db.onerror = function(event) { 
      // Generic error handler for all errors targeted at this database's requests 
      console.error(event.target); 
      window.alert("Database error: " + event.target.wePutrrorMessage || event.target.error.name || event.target.error || event.target.errorCode); 
     }; 
     var transaction = db.transaction('item', "readwrite"); 
     var itemStore = transaction.objectStore("item"); 
     putNext(); 

     function putNext() { 
      if (i<items.length) { 
       itemStore.put(items[i]).onsuccess = putNext; 
       ++i; 
      } else { // complete 
       console.log('populate complete'); 
       callback(); 
      } 
     }   
    };  
+0

İlginç bir öneri. Meraklı-performans kazanımları üzerinde herhangi bir kriter var mı? –

+0

Tüm öğelerin mağazada ** gerçekten ** olduğundan emin olmak için - "transaction.oncomplete" etkinliğine abone olun, smth like: 'transaction.oncomplete = callback' – Kiril

+0

Bir işlemin sonunu nasıl belirleyemiyorum biri işlemden bir mağaza alır, sonra bir veya daha fazla kayıt ekler ... Hepsini ekledikten sonra işlemi nasıl sonlandırırım? İşlem, geri arama geri dönüşleri döndükten sonra biter mi? Bu yinelemeli çağrıda tüm girdiler eklendikten sonra hangisi? bende öyle tahmin ediyorum – lisak

0

Geri dönüşleri kullanarak doğru olan her şeyi yapıyorsunuz.

Webworker API'si henüz herhangi bir büyük tarayıcı tarafından uygulanmadı. İlginç bir şekilde, senkron olması bekleniyor. Düzenli API, tanımlamanızın tam nedeni için belirsizdir - UI iş parçacığını engellememesi gerekir.

Geri aramaları kullanmak kilitlemeyi önlemenin bir yoludur, ancak 35k nesnelere bu paradigmanın bozulmasını açıkça görüyorsunuz. Ne yazık ki, IDB performansı henüz gördüğüm ölçütlerden WebSQL ile eşit değil.

Chrome'un LevelDB'sinde bazı yeni deneysel arka planlar (FF, SQLite) oldu, ancak deneyimlerinizin iyileştirme için bir yer olduğunu kanıtladığını düşünüyorum.

0

Benim tarafımdan vahşi tahmin, ancak WebSQL "arka plan sayfası" olarak bilinen bir şeyden varsa ve ön ve arka sayfa arasındaki mesajlaşma bant genişliği aynı şekilde UI kilitlemiyor varsayarak, belki içi sayfa iletisine sahip bir arkaplan sayfası kullanılabilir mi?

+0

Blok UI'sine neden olan for döngüsünün olduğunu hissediyorum. Düzenli aralıklarla tarayıcıya ping yapmanın bir yolu olsaydı, bu yüzden takılı kaldığını düşünmüyor. – surya

+0

Geleneksel GUI programlamada, tarayıcının ne zaman "boşta" olduğunu algılayabilir ve büyük foor döngüsünde başka bir adım atabilirsiniz. Ne yazık ki, boşta durumunu algılamak javascriptte kolay değil, ama bunu simüle etmek için hackler var. Örneğin http://stackoverflow.com/questions/667555/detecting-idle-time-in-javascript-elegantly. –

0

Diziyi 500'lük parçalar halinde bölüyorum ve döngü için setTimeout'u kullanıyorum. Artık UI,

+0

Birden çok olay döngüsü görevinden IndexedDB'ye erişmenizi önermem. Bu şekilde oldukça garip davranıyor – lisak

İlgili konular