Question

My intent

Loop through localStorage and put the data into IndexedDB. If certain known errors happen, such as a ConstraintError when a key already exists, I want to ignore those specific errors, so that the transaction is not aborted. Aborting the transaction is the default behaviour when a request triggers an error.

The problem

I thought that using event.preventDefault() in the request's onerror handler would prevent this from happening. Surprisingly, the event still surfaces in the transaction's error handler! I can see this happening by turning on logging (see the code below).

transaction.onerror = function (event) {
    log('IndexedDb.migrateLocalStorage -> transaction -> onerror', event.target.error.name);
};
transaction.oncomplete = function () {
    log('IndexedDb.migrateLocalStorage -> transaction -> oncomplete');
};

for (var key in $W.localStorage) {

    if ($W.localStorage.hasOwnProperty(key)) {
        value = $W.localStorage.getItem(key);
        request = objectStore.add(addQuotesIfNecessary(value), key);
        request.onerror = function (event) {
            var error = event.target.error;
            log('IndexedDb.migrateLocalStorage -> request -> onerror', error, error.name);

            // do nothing if the same key exists in indexeddb. it is likely newer
            if (error.name === 'ConstraintError') { event.preventDefault(); }
        };
    }
}
Was it helpful?

Solution

It seems the logging output from the code I pasted tricked me into thinking that the transaction was aborted, since the transaction.onerror handler was called. What I did not log, though, was whether transaction.onabort was called ... It turned out that a call to event.preventDefault actually was enough!

What confused me was that the error propagated up to the transaction error handler. The transaction was not aborted, though!. It just bubbled up the event after preventing the default action (aborting). To get rid of the message I also need to call event.stopPropagation in order to prevent the event from bubbling up to the transaction's error handler. Note that this is not strictly necessary if you just need the transaction to not be cancelled.

I found the answer by digging around in the W3C docs on IDBRequst and IBTransaction.

OTHER TIPS

It is logical that the transaction is in error when something goes wrong inside the transaction. That is way transactions exist, to keep the database consistent.

In your case you should better first check if the key exists. If it does, do nothing in the other case you can insert the data.

An other solution is opening a transaction for every object you want to save....

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top