diff --git a/client/components/Reader/Reader.vue b/client/components/Reader/Reader.vue index 7fe007a3..69366647 100644 --- a/client/components/Reader/Reader.vue +++ b/client/components/Reader/Reader.vue @@ -201,6 +201,7 @@ import miscApi from '../../api/misc'; import {versionHistory} from './versionHistory'; import * as utils from '../../share/utils'; +import LockQueue from '../../share/LockQueue'; const componentOptions = { components: { @@ -313,6 +314,8 @@ class Reader { this.reader = this.$store.state.reader; this.config = this.$store.state.config; + this.lock = new LockQueue(100); + this.$root.addEventHook('key', this.keyHook); this.lastActivePage = false; @@ -1051,7 +1054,7 @@ class Reader { return result; } - async loadBook(opts) { + async _loadBook(opts) { if (!opts || !opts.url) { this.mostRecentBook(); return; @@ -1061,10 +1064,6 @@ class Reader { let url = encodeURI(decodeURI(opts.url)); - //TODO: убрать конвертирование 'file://' после 06.2021 - if (url.length == 71 && url.indexOf('file://') == 0) - url = url.replace(/^file/, 'disk'); - if ((url.indexOf('http://') != 0) && (url.indexOf('https://') != 0) && (url.indexOf('disk://') != 0)) url = 'http://' + url; @@ -1189,7 +1188,16 @@ class Reader { } } - async loadFile(opts) { + async loadBook(opts) { + await this.lock.get(); + try { + await this._loadBook(opts); + } finally { + this.lock.ret(); + } + } + + async _loadFile(opts) { this.progressActive = true; await this.$nextTick(); @@ -1213,6 +1221,15 @@ class Reader { } } + async loadFile(opts) { + await this.lock.get(); + try { + await this._loadFile(opts); + } finally { + this.lock.ret(); + } + } + blinkCachedLoadMessage() { if (!this.blinkCachedLoad) return; diff --git a/client/share/LockQueue.js b/client/share/LockQueue.js new file mode 100644 index 00000000..ed350c57 --- /dev/null +++ b/client/share/LockQueue.js @@ -0,0 +1,53 @@ +class LockQueue { + constructor(queueSize) { + this.queueSize = queueSize; + this.freed = true; + this.waitingQueue = []; + } + + //async + get(take = true) { + return new Promise((resolve, reject) => { + if (this.freed) { + if (take) + this.freed = false; + resolve(); + return; + } + + if (this.waitingQueue.length < this.queueSize) { + this.waitingQueue.push({resolve, reject}); + } else { + reject(new Error('Lock queue is too long')); + } + }); + } + + ret() { + if (this.waitingQueue.length) { + this.waitingQueue.shift().resolve(); + } else { + this.freed = true; + } + } + + //async + wait() { + return this.get(false); + } + + retAll() { + while (this.waitingQueue.length) { + this.waitingQueue.shift().resolve(); + } + } + + errAll(error = 'rejected') { + while (this.waitingQueue.length) { + this.waitingQueue.shift().reject(new Error(error)); + } + } + +} + +export default LockQueue; \ No newline at end of file