From 4b8628637afceb5a06b1d08740e38cfe1d3a47d8 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Wed, 4 Sep 2024 11:08:56 +0200 Subject: [PATCH] Improve the `StructTreeLayerBuilder.render` method In hindsight it occurred to me that there's a couple of smaller issues with this method after it's made asynchronous (in PR 18658). - If the `render`-method is invoked back-to-back the existing caching doesn't guarantee that re-parsing won't occur, which we can address by introducing a new (private) promise. - If there's any errors fetching and/or parsing the structTree-data, we'd attempt to parse it again on re-rendering despite that being pointless. --- web/struct_tree_layer_builder.js | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/web/struct_tree_layer_builder.js b/web/struct_tree_layer_builder.js index 19de6f72025d8..4e117eacec99e 100644 --- a/web/struct_tree_layer_builder.js +++ b/web/struct_tree_layer_builder.js @@ -76,7 +76,9 @@ const HEADING_PATTERN = /^H(\d+)$/; class StructTreeLayerBuilder { #promise; - #treeDom = undefined; + #treeDom = null; + + #treePromise; #elementAttributes = new Map(); @@ -85,13 +87,23 @@ class StructTreeLayerBuilder { } async render() { - if (this.#treeDom !== undefined) { - return this.#treeDom; + if (this.#treePromise) { + return this.#treePromise; + } + const { promise, resolve, reject } = Promise.withResolvers(); + this.#treePromise = promise; + + try { + this.#treeDom = this.#walk(await this.#promise); + } catch (ex) { + reject(ex); } - const treeDom = (this.#treeDom = this.#walk(await this.#promise)); this.#promise = null; - treeDom?.classList.add("structTree"); - return treeDom; + + this.#treeDom?.classList.add("structTree"); + resolve(this.#treeDom); + + return promise; } async getAriaAttributes(annotationId) {