Closed nstgmk closed 6 years ago
Thanks! This is great insight for solving this problem once and for all. We should consider how to deal with it; currently there is a fallback to the in-memory cache so the app is working in case of problesm with cache not responding - like normally. The downside is that if this problem will happen - then nothing is stored in the persistent storage (so after reloading the page shopping cart, user token - all will lost).
The simplest way to work around it is just to modify the: https://github.com/DivanteLtd/vue-storefront/blob/6be64960d9dc5e728fcdda75068f80d8dbc8436a/core/store/lib/storage.js#L42
to add the ready()
chain before setItem(), getItem():
https://localforage.github.io/localForage/#driver-api-ready
Could You test it, please?
Great suggestion! I've given it a try now. I changed getItem
to the following:
getItem (key, callback) {
const self = this
const isCallbackCallable = (typeof callback !== 'undefined' && callback)
let isResolved = false
if (self._useLocalCacheByDefault && self._localCache[key]) {
// console.debug('Local cache fallback for GET', key)
return new Promise((resolve, reject) => {
const value = typeof self._localCache[key] !== 'undefined' ? self._localCache[key] : null
if (isCallbackCallable) callback(null, value)
resolve(value)
})
}
// console.debug('No local cache fallback for GET', key)
const promise = this._localForageCollection.ready().then(function () {
self._localForageCollection.getItem(key).then(result => {
if (!isResolved) {
if (isCallbackCallable) {
callback(null, result)
}
isResolved = true
} else {
console.debug('Skipping return value as it was previously resolved')
}
return result
})
}).catch(err => {
console.debug('UniversalStorage - GET - probably in SSR mode: ' + err)
if (!isResolved) {
if (isCallbackCallable) callback(null, typeof self._localCache[key] !== 'undefined' ? self._localCache[key] : null)
}
isResolved = true
})
setTimeout(function () {
if (!isResolved) { // this is cache time out check
console.error('Cache not responding within 1s')
if (isCallbackCallable) callback(null, typeof self._localCache[key] !== 'undefined' ? self._localCache[key] : null)
}
}, 1000)
return promise
}
And it worked great! No more error messages and IndexedDB stores persistently. I tried to the same with setItem
:
setItem (key, value, callback) {
const self = this
const isCallbackCallable = (typeof callback !== 'undefined' && callback)
self._localCache[key] = value
const promise = self._localForageCollection.ready().then(function () {
self._localForageCollection.setItem(key, value).then(result => {
if (isCallbackCallable) {
callback(null, result)
}
})
}).catch(err => {
console.debug('UniversalStorage - SET - probably in SSR mode: ' + err)
})
return promise
}
But this was not successful. I got the same error message that the cache was not responding and also a new error Uncaught (in promise) TypeError: Cannot read property 'db' of null
. It looks like the db connection is lost. Maybe it's not possible to check if ready here?
However, when I didn't edit setItem
and only changed getItem
everything works for me.
That's cool - in the meantime I've fixed it in parallel to Your fix: https://github.com/DivanteLtd/vue-storefront/commit/079a2f002999dc0b3ced64a4c06e9b5c64aaecea
:)
For me it works for setItem
as well. The message You're getting is probably caused by some other reason ..
You're probably right :) I'll try your solution instead and see if it works. Thanks!
Thanks! Without Your observation i wouldn't have fix it! :)
When I clear the browser cache, enter my store's home page and then navigate to any category or product page I get the error message "Cache not responding". After this happens and I check Application > IndexedDB in Chrome I can see that nothing gets added to the database. For example, if I try to add something to the cart I can see that it's not added in the database. I can place an order in the checkout but it's not sent to the backend for processing at all. It's not found in syncTasks either.
Refreshing the page solves the problem. The problem appears in my dev store running v1.0.5 and the vue storefront demo page. I haven't checked if it's present in developer build.
I tried looking into the problem myself and found out that something seems to happen in lib/search.js in the function
quickSearchByQuery
. If I callready()
onglobal.$VS.db.elasticCacheCollection._localForageCollection
I can see that the promise is pending and not resolved at the timegetItem
is called.I used the promise from
ready()
and placed the wholecache.getItem
block inside the then() part and this solved the problem. IndexedDB shows items as expected, no error message and no refresh needed.I'm new to JS and Vue development so I'd appreciate if someone more experienced could look into this and maybe find a better solution or explain what happens. But it seems like elasticCacheCollection is just not ready when it's called? Is there a better way to wait for it?
Thanks!