Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 36 additions & 52 deletions src/htmx.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,58 +87,42 @@ var htmx = (() => {
},
};

class ReqQ {
#c = null
#q = []

issue(ctx, queueStrategy) {
ctx.queueStrategy = queueStrategy
if (!this.#c) {
this.#c = ctx
return true
class RequestQueue {
#current = null
#queue = []

/** Returns "run", "queued", or "dropped" */
admit(strategy, runRequest, abortRequest) {
if (!this.#current) {
this.#current = {strategy, abort: abortRequest}
return "run"
}
if (strategy === "replace" || (strategy !== "abort" && this.#current.strategy === "abort")) {
this.#queue = []
this.#current.abort?.()
this.#current = {strategy, abort: abortRequest}
return "run"
}
if (strategy === "queue all") {
this.#queue.push(runRequest)
} else if (strategy === "queue last") {
this.#queue = [runRequest]
} else if (strategy !== "abort" && strategy !== "drop" && this.#queue.length === 0) {
// default queue first
this.#queue.push(runRequest)
} else {
// Replace strategy OR current is abortable: abort current and issue new
if (queueStrategy === "replace" || (queueStrategy !== "abort" && this.#c.queueStrategy === "abort")) {
this.#q.forEach(value => value.status = "dropped");
this.#q = []
this.#c.request?.abort?.();
this.#c = ctx
return true
} else if (queueStrategy === "queue all") {
this.#q.push(ctx)
ctx.status = "queued";
} else if (queueStrategy === "drop") {
// ignore the request
ctx.status = "dropped";
} else if (queueStrategy === "queue last") {
this.#q.forEach(value => value.status = "dropped");
this.#q = [ctx]
ctx.status = "queued";
} else if (this.#q.length === 0 && queueStrategy !== "abort") {
// default queue first
this.#q.push(ctx)
ctx.status = "queued";
} else {
ctx.status = "dropped";
}
return false
return "dropped"
}
return "queued"
}

finish() {
this.#c = null
}

next() {
return this.#q.shift()
continue() {
this.#current = null // free current slot
this.#queue.shift()?.() // run next request
}

abort() {
this.#c?.request?.abort?.()
}

more() {
return this.#q?.length
this.#current?.abort?.()
}
}

Expand Down Expand Up @@ -581,7 +565,11 @@ var htmx = (() => {
let syncStrategy = this.__determineSyncStrategy(elt);
let requestQueue = this.__getRequestQueue(elt);

if (!requestQueue.issue(ctx, syncStrategy)) return
if (requestQueue.admit(
syncStrategy,
() => this.__issueRequest(ctx), // run when ready
() => ctx.request?.abort?.() // abort if replaced
) !== "run") return

ctx.status = "issuing"

Expand Down Expand Up @@ -653,11 +641,7 @@ var htmx = (() => {
this.__enableElements(disableElements);
}

requestQueue.finish()
if (requestQueue.more()) {
// intentionally not awaited — __issueRequest has its own try/catch
this.__issueRequest(requestQueue.next())
}
requestQueue.continue()
}
}

Expand Down Expand Up @@ -721,7 +705,7 @@ var htmx = (() => {
: (/^(drop|abort|replace|queue)/.test(hxSync) ? null : hxSync);
if (selector) syncElt = this.__findOrWarn(elt, selector, "hx-sync") || elt;
}
return this.__htmxState(syncElt).rq ||= new ReqQ()
return this.__htmxState(syncElt).rq ||= new RequestQueue()
}

__isModifierKeyClick(evt) {
Expand Down
Loading
Loading