Добавлено кеширование запросов на клиенте
This commit is contained in:
@@ -151,6 +151,7 @@
|
|||||||
|
|
||||||
<q-checkbox v-model="showCounts" size="36px" label="Показывать количество" />
|
<q-checkbox v-model="showCounts" size="36px" label="Показывать количество" />
|
||||||
<q-checkbox v-model="showDeleted" size="36px" label="Показывать удаленные" />
|
<q-checkbox v-model="showDeleted" size="36px" label="Показывать удаленные" />
|
||||||
|
<q-checkbox v-model="abCacheEnabled" size="36px" label="Кешировать запросы" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@@ -168,6 +169,7 @@ import vueComponent from '../vueComponent.js';
|
|||||||
import { reactive } from 'vue';
|
import { reactive } from 'vue';
|
||||||
|
|
||||||
import PageScroller from './PageScroller/PageScroller.vue';
|
import PageScroller from './PageScroller/PageScroller.vue';
|
||||||
|
import authorBooksStorage from './authorBooksStorage';
|
||||||
import DivBtn from '../share/DivBtn.vue';
|
import DivBtn from '../share/DivBtn.vue';
|
||||||
import Dialog from '../share/Dialog.vue';
|
import Dialog from '../share/Dialog.vue';
|
||||||
|
|
||||||
@@ -218,6 +220,9 @@ const componentOptions = {
|
|||||||
showDeleted(newValue) {
|
showDeleted(newValue) {
|
||||||
this.setSetting('showDeleted', newValue);
|
this.setSetting('showDeleted', newValue);
|
||||||
},
|
},
|
||||||
|
abCacheEnabled(newValue) {
|
||||||
|
this.setSetting('abCacheEnabled', newValue);
|
||||||
|
},
|
||||||
totalFound() {
|
totalFound() {
|
||||||
this.updatePageCount();
|
this.updatePageCount();
|
||||||
},
|
},
|
||||||
@@ -250,11 +255,13 @@ class Search {
|
|||||||
expanded = [];
|
expanded = [];
|
||||||
showCounts = true;
|
showCounts = true;
|
||||||
showDeleted = false;
|
showDeleted = false;
|
||||||
|
abCacheEnabled = true;
|
||||||
|
|
||||||
//stuff
|
//stuff
|
||||||
queryFound = -1;
|
queryFound = -1;
|
||||||
totalFound = 0;
|
totalFound = 0;
|
||||||
bookRowsOnPage = 100;
|
bookRowsOnPage = 100;
|
||||||
|
inpxHash = '';
|
||||||
|
|
||||||
limitOptions = [
|
limitOptions = [
|
||||||
{label: '10', value: 10},
|
{label: '10', value: 10},
|
||||||
@@ -276,13 +283,17 @@ class Search {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.api = this.$root.api;
|
(async() => {
|
||||||
|
await authorBooksStorage.init();
|
||||||
|
|
||||||
if (!this.$root.isMobileDevice)
|
this.api = this.$root.api;
|
||||||
this.$refs.authorInput.focus();
|
|
||||||
|
|
||||||
this.ready = true;
|
if (!this.$root.isMobileDevice)
|
||||||
this.refresh();//no await
|
this.$refs.authorInput.focus();
|
||||||
|
|
||||||
|
this.ready = true;
|
||||||
|
this.refresh();//no await
|
||||||
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
loadSettings() {
|
loadSettings() {
|
||||||
@@ -290,7 +301,9 @@ class Search {
|
|||||||
|
|
||||||
this.limit = settings.limit;
|
this.limit = settings.limit;
|
||||||
this.expanded = _.cloneDeep(settings.expanded);
|
this.expanded = _.cloneDeep(settings.expanded);
|
||||||
|
this.showCounts = settings.showCounts;
|
||||||
this.showDeleted = settings.showDeleted;
|
this.showDeleted = settings.showDeleted;
|
||||||
|
this.abCacheEnabled = settings.abCacheEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
get config() {
|
get config() {
|
||||||
@@ -438,9 +451,23 @@ class Search {
|
|||||||
return `(${result})`;
|
return `(${result})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadBooks(author, authorId) {
|
async loadBooks(authorId) {
|
||||||
try {
|
try {
|
||||||
const result = await this.api.getBookList(authorId);
|
let result;
|
||||||
|
|
||||||
|
const key = `${authorId}-${this.inpxHash}`;
|
||||||
|
|
||||||
|
if (this.abCacheEnabled) {
|
||||||
|
const data = await authorBooksStorage.getData(key);
|
||||||
|
if (data) {
|
||||||
|
result = JSON.parse(data);
|
||||||
|
} else {
|
||||||
|
result = await this.api.getBookList(authorId);
|
||||||
|
await authorBooksStorage.setData(key, JSON.stringify(result));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = await this.api.getBookList(authorId);
|
||||||
|
}
|
||||||
|
|
||||||
return JSON.parse(result.books);
|
return JSON.parse(result.books);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -470,7 +497,7 @@ class Search {
|
|||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadedBooks = await this.loadBooks(item.author, item.key);
|
const loadedBooks = await this.loadBooks(item.key);
|
||||||
|
|
||||||
const filtered = this.filterBooks(loadedBooks);
|
const filtered = this.filterBooks(loadedBooks);
|
||||||
|
|
||||||
@@ -561,6 +588,7 @@ class Search {
|
|||||||
|
|
||||||
this.queryFound = result.author.length;
|
this.queryFound = result.author.length;
|
||||||
this.totalFound = result.totalFound;
|
this.totalFound = result.totalFound;
|
||||||
|
this.inpxHash = result.inpxHash;
|
||||||
|
|
||||||
this.searchResult = result;
|
this.searchResult = result;
|
||||||
await this.updateTableData();
|
await this.updateTableData();
|
||||||
|
|||||||
74
client/components/Search/authorBooksStorage.js
Normal file
74
client/components/Search/authorBooksStorage.js
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import localForage from 'localforage';
|
||||||
|
//import _ from 'lodash';
|
||||||
|
import * as utils from '../../share/utils';
|
||||||
|
|
||||||
|
const maxDataSize = 100*1024*1024;
|
||||||
|
|
||||||
|
const abStore = localForage.createInstance({
|
||||||
|
name: 'authorBooksStorage'
|
||||||
|
});
|
||||||
|
|
||||||
|
class AuthorBooksStorage {
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
this.cleanStorage(); //no await
|
||||||
|
}
|
||||||
|
|
||||||
|
async setData(key, data) {
|
||||||
|
if (typeof data !== 'string')
|
||||||
|
throw new Error('AuthorBooksStorage: data must be a string');
|
||||||
|
|
||||||
|
await abStore.setItem(key, data);
|
||||||
|
await abStore.setItem(`addTime-${key}`, Date.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
async getData(key) {
|
||||||
|
const item = await abStore.getItem(key);
|
||||||
|
|
||||||
|
//обновим addTime
|
||||||
|
if (item !== undefined)
|
||||||
|
abStore.setItem(`addTime-${key}`, Date.now());//no await
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeData(key) {
|
||||||
|
await abStore.removeItem(key);
|
||||||
|
await abStore.removeItem(`addTime-${key}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async cleanStorage() {
|
||||||
|
await utils.sleep(5000);
|
||||||
|
|
||||||
|
while (1) {// eslint-disable-line no-constant-condition
|
||||||
|
let size = 0;
|
||||||
|
let min = Date.now();
|
||||||
|
let toDel = null;
|
||||||
|
for (const key of (await abStore.keys())) {
|
||||||
|
if (key.indexOf('addTime-') == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const item = await abStore.getItem(key);
|
||||||
|
const addTime = await abStore.getItem(`addTime-${key}`);
|
||||||
|
|
||||||
|
size += item.length;
|
||||||
|
|
||||||
|
if (addTime < min) {
|
||||||
|
toDel = key;
|
||||||
|
min = addTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size > maxDataSize && toDel) {
|
||||||
|
await this.removeData(toDel);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new AuthorBooksStorage();
|
||||||
@@ -6,6 +6,7 @@ const state = {
|
|||||||
expanded: [],
|
expanded: [],
|
||||||
showCounts: true,
|
showCounts: true,
|
||||||
showDeleted: false,
|
showDeleted: false,
|
||||||
|
abCacheEnabled: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user