Оптимизация загрузки и хранения списка недавних книг
This commit is contained in:
@@ -507,10 +507,10 @@ class ServerStorage extends Vue {
|
|||||||
if (md.key && result[md.key])
|
if (md.key && result[md.key])
|
||||||
result[md.key] = utils.applyObjDiff(result[md.key], md.mod, {isAddChanged: true});
|
result[md.key] = utils.applyObjDiff(result[md.key], md.mod, {isAddChanged: true});
|
||||||
|
|
||||||
if (!bookManager.loaded) {
|
/*if (!bookManager.loaded) {
|
||||||
this.warning('Ожидание загрузки списка книг перед синхронизацией');
|
this.warning('Ожидание загрузки списка книг перед синхронизацией');
|
||||||
while (!bookManager.loaded) await utils.sleep(100);
|
while (!bookManager.loaded) await utils.sleep(100);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if (newRecent.rev != this.cachedRecent.rev)
|
if (newRecent.rev != this.cachedRecent.rev)
|
||||||
await this.setCachedRecent(newRecent);
|
await this.setCachedRecent(newRecent);
|
||||||
|
|||||||
@@ -17,9 +17,12 @@ const bmDataStore = localForage.createInstance({
|
|||||||
});
|
});
|
||||||
|
|
||||||
//список недавно открытых книг
|
//список недавно открытых книг
|
||||||
const bmRecentStore = localForage.createInstance({
|
const bmRecentStoreOld = localForage.createInstance({
|
||||||
name: 'bmRecentStore'
|
name: 'bmRecentStore'
|
||||||
});
|
});
|
||||||
|
const bmRecentStoreNew = localForage.createInstance({
|
||||||
|
name: 'bmRecentStoreNew'
|
||||||
|
});
|
||||||
|
|
||||||
class BookManager {
|
class BookManager {
|
||||||
async init(settings) {
|
async init(settings) {
|
||||||
@@ -28,15 +31,74 @@ class BookManager {
|
|||||||
|
|
||||||
this.eventListeners = [];
|
this.eventListeners = [];
|
||||||
this.books = {};
|
this.books = {};
|
||||||
this.recent = {};
|
|
||||||
|
|
||||||
this.recentLast = await bmRecentStore.getItem('recent-last');
|
this.recent = {};
|
||||||
if (this.recentLast) {
|
this.saveRecent = _.debounce(() => {
|
||||||
this.recent[this.recentLast.key] = this.recentLast;
|
bmRecentStoreNew.setItem('recent', this.recent);
|
||||||
const meta = await bmMetaStore.getItem(`bmMeta-${this.recentLast.key}`);
|
}, 300, {maxWait: 800});
|
||||||
if (_.isObject(meta)) {
|
|
||||||
this.books[meta.key] = meta;
|
this.saveRecentItem = _.debounce(() => {
|
||||||
|
bmRecentStoreNew.setItem('recent-item', this.recentItem);
|
||||||
|
this.recentRev++;
|
||||||
|
bmRecentStoreNew.setItem('rev', this.recentRev);
|
||||||
|
}, 200, {maxWait: 300});
|
||||||
|
|
||||||
|
//загрузка bmRecentStore
|
||||||
|
this.recentRev = await bmRecentStoreNew.getItem('rev') || 0;
|
||||||
|
if (this.recentRev) {
|
||||||
|
this.recent = await bmRecentStoreNew.getItem('recent');
|
||||||
|
if (!this.recent)
|
||||||
|
this.recent = {};
|
||||||
|
|
||||||
|
this.recentItem = await bmRecentStoreNew.getItem('recent-item');
|
||||||
|
if (this.recentItem)
|
||||||
|
this.recent[this.recentItem.key] = this.recentItem;
|
||||||
|
|
||||||
|
this.recentLastKey = await bmRecentStoreNew.getItem('recent-last-key');
|
||||||
|
if (this.recentLastKey) {
|
||||||
|
const meta = await bmMetaStore.getItem(`bmMeta-${this.recentLastKey}`);
|
||||||
|
if (_.isObject(meta)) {
|
||||||
|
this.books[meta.key] = meta;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.cleanRecentBooks();
|
||||||
|
|
||||||
|
} else {//TODO: убрать после 06.2021, когда bmRecentStoreOld устареет
|
||||||
|
this.recentLast = await bmRecentStoreOld.getItem('recent-last');
|
||||||
|
if (this.recentLast) {
|
||||||
|
this.recent[this.recentLast.key] = this.recentLast;
|
||||||
|
const meta = await bmMetaStore.getItem(`bmMeta-${this.recentLast.key}`);
|
||||||
|
if (_.isObject(meta)) {
|
||||||
|
this.books[meta.key] = meta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let key = null;
|
||||||
|
const len = await bmRecentStoreOld.length();
|
||||||
|
for (let i = len - 1; i >= 0; i--) {
|
||||||
|
key = await bmRecentStoreOld.key(i);
|
||||||
|
if (key) {
|
||||||
|
let r = await bmRecentStoreOld.getItem(key);
|
||||||
|
if (_.isObject(r) && r.key) {
|
||||||
|
this.recent[r.key] = r;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await bmRecentStoreOld.removeItem(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//размножение для дебага
|
||||||
|
/*if (key) {
|
||||||
|
for (let i = 0; i < 1000; i++) {
|
||||||
|
const k = this.keyFromUrl(i.toString());
|
||||||
|
this.recent[k] = Object.assign({}, _.cloneDeep(this.recent[key]), {key: k, touchTime: Date.now() - 1000000, url: utils.randomHexString(300)});
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
await bmRecentStoreNew.setItem('recent', this.recent);
|
||||||
|
this.recentRev = 1;
|
||||||
|
await bmRecentStoreNew.setItem('rev', this.recentRev);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.recentChanged = true;
|
this.recentChanged = true;
|
||||||
@@ -44,9 +106,7 @@ class BookManager {
|
|||||||
this.loadStored();//no await
|
this.loadStored();//no await
|
||||||
}
|
}
|
||||||
|
|
||||||
//Долгая асинхронная загрузка из хранилища.
|
//Ленивая асинхронная загрузка bmMetaStore
|
||||||
//Хранение в отдельных записях дает относительно
|
|
||||||
//нормальное поведение при нескольких вкладках с читалкой в браузере.
|
|
||||||
async loadStored() {
|
async loadStored() {
|
||||||
//даем время для загрузки последней читаемой книги, чтобы не блокировать приложение
|
//даем время для загрузки последней читаемой книги, чтобы не блокировать приложение
|
||||||
await utils.sleep(2000);
|
await utils.sleep(2000);
|
||||||
@@ -73,32 +133,7 @@ class BookManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = null;
|
|
||||||
len = await bmRecentStore.length();
|
|
||||||
for (let i = len - 1; i >= 0; i--) {
|
|
||||||
key = await bmRecentStore.key(i);
|
|
||||||
if (key) {
|
|
||||||
let r = await bmRecentStore.getItem(key);
|
|
||||||
if (_.isObject(r) && r.key) {
|
|
||||||
this.recent[r.key] = r;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await bmRecentStore.removeItem(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//размножение для дебага
|
|
||||||
/*if (key) {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
const k = this.keyFromUrl(i.toString());
|
|
||||||
this.recent[k] = Object.assign({}, _.cloneDeep(this.recent[key]), {key: k, touchTime: Date.now() - 1000000, url: utils.randomHexString(300)});
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
await this.cleanBooks();
|
await this.cleanBooks();
|
||||||
await this.cleanRecentBooks();
|
|
||||||
|
|
||||||
this.recentChanged = true;
|
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
this.emit('load-stored-finish');
|
this.emit('load-stored-finish');
|
||||||
}
|
}
|
||||||
@@ -331,6 +366,43 @@ class BookManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-- recent --------------------------------------------------------------
|
//-- recent --------------------------------------------------------------
|
||||||
|
async recentSetItem(item = null, skipCheck = false) {
|
||||||
|
const rev = await bmRecentStoreNew.getItem('rev');
|
||||||
|
if (rev != this.recentRev && !skipCheck) {
|
||||||
|
const newRecent = await bmRecentStoreNew.getItem('recent');
|
||||||
|
Object.assign(this.recent, newRecent);
|
||||||
|
this.recentItem = await bmRecentStoreNew.getItem('recent-item');
|
||||||
|
this.recentRev = rev;
|
||||||
|
}
|
||||||
|
|
||||||
|
const prevKey = (this.recentItem ? this.recentItem.key : '');
|
||||||
|
if (item) {
|
||||||
|
this.recent[item.key] = item;
|
||||||
|
this.recentItem = item;
|
||||||
|
} else {
|
||||||
|
this.recentItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveRecentItem();
|
||||||
|
|
||||||
|
if (!item || prevKey != item.key) {
|
||||||
|
this.saveRecent();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.recentChanged = true;
|
||||||
|
|
||||||
|
if (item) {
|
||||||
|
this.emit('recent-changed', item.key);
|
||||||
|
} else {
|
||||||
|
this.emit('recent-changed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async recentSetLastKey(key) {
|
||||||
|
this.recentLastKey = key;
|
||||||
|
await bmRecentStoreNew.setItem('recent-last-key', this.recentLastKey);
|
||||||
|
}
|
||||||
|
|
||||||
async setRecentBook(value) {
|
async setRecentBook(value) {
|
||||||
const result = this.metaOnly(value);
|
const result = this.metaOnly(value);
|
||||||
result.touchTime = Date.now();
|
result.touchTime = Date.now();
|
||||||
@@ -344,38 +416,25 @@ class BookManager {
|
|||||||
result.bookPosSeen = this.recent[result.key].bookPosSeen;
|
result.bookPosSeen = this.recent[result.key].bookPosSeen;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.recent[result.key] = result;
|
await this.recentSetLastKey(result.key);
|
||||||
|
await this.recentSetItem(result);
|
||||||
await bmRecentStore.setItem(result.key, result);
|
|
||||||
|
|
||||||
this.recentLast = result;
|
|
||||||
await bmRecentStore.setItem('recent-last', this.recentLast);
|
|
||||||
|
|
||||||
this.recentChanged = true;
|
|
||||||
this.emit('recent-changed', result.key);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRecentBook(value) {
|
async getRecentBook(value) {
|
||||||
let result = this.recent[value.key];
|
return this.recent[value.key];
|
||||||
if (!result) {
|
|
||||||
result = await bmRecentStore.getItem(value.key);
|
|
||||||
if (result)
|
|
||||||
this.recent[value.key] = result;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async delRecentBook(value) {
|
async delRecentBook(value) {
|
||||||
this.recent[value.key].deleted = 1;
|
const item = this.recent[value.key];
|
||||||
await bmRecentStore.setItem(value.key, this.recent[value.key]);
|
item.deleted = 1;
|
||||||
|
|
||||||
if (this.recentLast.key == value.key) {
|
if (this.recentLastKey == value.key) {
|
||||||
this.recentLast = null;
|
await this.recentSetLastKey(null);
|
||||||
await bmRecentStore.setItem('recent-last', this.recentLast);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.recentSetItem(item);
|
||||||
this.emit('recent-deleted', value.key);
|
this.emit('recent-deleted', value.key);
|
||||||
this.emit('recent-changed', value.key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async cleanRecentBooks() {
|
async cleanRecentBooks() {
|
||||||
@@ -383,24 +442,22 @@ class BookManager {
|
|||||||
|
|
||||||
let isDel = false;
|
let isDel = false;
|
||||||
for (let i = 1000; i < sorted.length; i++) {
|
for (let i = 1000; i < sorted.length; i++) {
|
||||||
await bmRecentStore.removeItem(sorted[i].key);
|
|
||||||
delete this.recent[sorted[i].key];
|
delete this.recent[sorted[i].key];
|
||||||
await bmRecentStore.removeItem(sorted[i].key);
|
|
||||||
isDel = true;
|
isDel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sortedRecentCached = null;
|
this.sortedRecentCached = null;
|
||||||
|
|
||||||
if (isDel)
|
if (isDel)
|
||||||
this.emit('recent-changed');
|
await this.recentSetItem();
|
||||||
return isDel;
|
return isDel;
|
||||||
}
|
}
|
||||||
|
|
||||||
mostRecentBook() {
|
mostRecentBook() {
|
||||||
if (this.recentLast) {
|
if (this.recentLastKey) {
|
||||||
return this.recentLast;
|
return this.recent[this.recentLastKey];
|
||||||
}
|
}
|
||||||
const oldRecentLast = this.recentLast;
|
const oldKey = this.recentLastKey;
|
||||||
|
|
||||||
let max = 0;
|
let max = 0;
|
||||||
let result = null;
|
let result = null;
|
||||||
@@ -411,10 +468,11 @@ class BookManager {
|
|||||||
result = book;
|
result = book;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.recentLast = result;
|
|
||||||
bmRecentStore.setItem('recent-last', this.recentLast);//no await
|
const newRecentLastKey = (result ? result.key : null);
|
||||||
|
this.recentSetLastKey(newRecentLastKey);//no await
|
||||||
|
|
||||||
if (this.recentLast !== oldRecentLast)
|
if (newRecentLastKey !== oldKey)
|
||||||
this.emit('recent-changed');
|
this.emit('recent-changed');
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -445,24 +503,12 @@ class BookManager {
|
|||||||
delete mergedRecent[i];
|
delete mergedRecent[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
//"ленивое" обновление хранилища
|
|
||||||
(async() => {
|
|
||||||
for (const rec of Object.values(mergedRecent)) {
|
|
||||||
if (rec.key) {
|
|
||||||
await bmRecentStore.setItem(rec.key, rec);
|
|
||||||
await utils.sleep(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
this.recent = mergedRecent;
|
this.recent = mergedRecent;
|
||||||
|
|
||||||
this.recentLast = null;
|
await this.recentSetLastKey(null);
|
||||||
await bmRecentStore.setItem('recent-last', this.recentLast);
|
await this.recentSetItem(null, true);
|
||||||
|
|
||||||
this.recentChanged = true;
|
|
||||||
this.emit('set-recent');
|
this.emit('set-recent');
|
||||||
this.emit('recent-changed');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addEventListener(listener) {
|
addEventListener(listener) {
|
||||||
|
|||||||
Reference in New Issue
Block a user