2012-05-06 9 views
15

Desidero salvare circa ~ 35000 oggetti nell'oggetore del mio IndexedDB. Sto usando sotto il codice da inserire.Inserimento di grandi quantità nei blocchi di oggetti di IndexedDB 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 
      }; 
     }); 
    });   
}; 

Il codice sopra funziona bene, ma il ciclo e l'inserimento di più di ~ 35000 oggetti rende l'interfaccia utente non risponde per ~ 200 secondi. Ho pensato che forse potrei usare WebWorkers, ma IndexedDB non è disponibile all'interno di WebWorkers. Ho cercato di trovare un modo per inserire in blocco, non ho trovato uno. Qualche idea su come inserire grandi quantità di oggetti senza bloccare l'interfaccia utente?

+1

Per ora sto dividendo la matrice in [pezzi] (http://stackoverflow.com/questions/ 8495687/split-array-in-chunks) di 500 e utilizzando [setInterval] (http://www.kryogenix.org/days/2009/07/03/not-blocking-the-ui-in-tight-javascript- loop) anziché per loop. Ora l'interfaccia utente risponde poco meglio di prima. – surya

risposta

28

Sei sulla strada giusta, ma stai chiedendo al browser di memorizzare 35.000 oggetti prima che abbia la possibilità di terminarne uno. Ecco il codice che attende in modo asincrono per una richiesta di finire prima di iniziare il prossimo (ma usando la stessa operazione):

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

Suggerimento interessante. Curioso. Qualcuno ha qualche benchmark sui guadagni in termini di prestazioni ottenuti? –

+0

Per essere sicuri che tutti gli articoli siano ** veramente ** nell'archivio - iscriviti all'evento 'transaction.oncomplete', come:' transaction.oncomplete = callback' – Kiril

+0

Non riesco a vedere come determinare la fine di una transazione , si ottiene un negozio dalla transazione quindi si aggiungono uno o più record ... Come posso concludere la transazione dopo averlo aggiunto tutto? La transazione termina dopo il ritorno di callback di successo? Qual è dopo che tutte le voci sono state aggiunte in questa chiamata ricorsiva? suppongo di sì – lisak

0

Stai facendo tutto bene usando i callback.

L'API di Webworker non è stata ancora implementata da alcun browser principale. È interessante notare che dovrebbe essere sincrono. L'API regolare è asincrona per il motivo esatto che descrivi - non si suppone che blocchi il thread dell'interfaccia utente.

L'utilizzo di callback è un modo per evitare blocchi, ma a 35k oggetti si vede chiaramente che questo paradigma si interrompe. Sfortunatamente, le prestazioni di IDB non sono ancora alla pari con WebSQL rispetto ai benchmark che ho visto.

Con Chrome's LevelDB ci sono stati alcuni nuovi backend sperimentali (FF è SQLite) ma penso che la tua esperienza dimostri che ci sono margini di miglioramento.

0

Wild congettura da parte mia, ma se WebSQL è disponibile da quella che è nota come "pagina di sfondo", e supponendo che la larghezza di banda della messaggistica tra front-and backpage non blocchi l'interfaccia utente nello stesso modo, forse potrebbe essere utilizzata una pagina di sfondo con il messaggio della pagina intra?

+0

Ho la sensazione che sia il ciclo for che sta causando l'UI del blocco. Mi piacerebbe che ci fosse un modo per eseguire il ping del browser in intervalli regolari, quindi non credo che sia bloccato – surya

+0

Nella programmazione della GUI tradizionale, è possibile rilevare quando il browser è "inattivo" ed eseguire un altro passo nel ciclo big foor. Sfortunatamente, il rilevamento dello stato di inattività non è facile in javascript, ma esistono degli hack per simularlo. Ad esempio http://stackoverflow.com/questions/667555/detecting-idle-time-in-javascript-elegantly. –

0

Sto dividendo l'array in blocchi di 500 e utilizzando setTimeout anziché per ciclo. Ora l'interfaccia utente risponde poco meglio di prima

+0

Non è consigliabile accedere a IndexedDB da più attività del ciclo di eventi. Si comporta in modo strano in questo modo – lisak

Problemi correlati