RFC: polling is the element's lifetime (htmx 4, #4040) #4048
manwithacat
started this conversation in
Ideas
Replies: 1 comment
|
Draft PR (not for merge until this discussion lands): #4049 |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
#4040 asks how four should cancel
hx-trigger="every …". The 2.x answers were a magic status (286), a cancelled flag, and (in #2576) a header, an event, andcancelPollingOnError. Four dropped all of that:setIntervalon the node,clearIntervalwhen the node is gone.This RFC argues that is not a hole. It is the hypermedia rule, and it should be the canonical 4.x model.
The poll is a representation
htmx’s bet is that HTML is the state. A node with
hx-trigger="every 2s"is a poller. A node without it is not. The server does not send a command (“stop polling”). It sends a new representation.That is the same idea as a link that disappears when the action is no longer available, or a form that is replaced by a confirmation. 286 is the other shape: “keep this element, but change a hidden client flag.” The DOM still looks like a poller.
process()would arm it again. A publichtmx.cancelPolling()/resumePolling()has the same problem unless it also rewrites the attributes — at which point you have reimplemented a swap.The 4.x runtime already matches the HTML-as-state story:
__cleanupclears the timer on swap. The polling and progress bar demos already stop by omittinghx-triggeron the morphed element.What 286 was papering over
innerHTML+everycannot self-stop. The poller is the outer node; innerHTML never replaces it, soisConnectedstays true. 286 existed so the server could cancel without changing that node.Four can say that out loud instead of restoring a status code:
outerHTML/outerMorph, orHX-Reswap: outerHTMLwhen the request would otherwise innerHTML).hx-ptag/ 304, not cancel.[document.visibilityState === 'visible']), not cancel. The interval lives; the request does not.everyis the fallback heartbeat, not a faster poll.We had to learn this the slow way
We maintain a server-rendered app on htmx 4. When 286 became a silent no-op, polls that used to stop just… did not. The fix was not a JS API. It was the progress-bar pattern applied on the server: return the polling element without
every, withHX-Reswap: outerHTMLwhen the request was innerHTML. SSE for the live path,everyas the heartbeat. That is already in the demos. It was not written down as the rule, so 2.x muscle memory (return 286) kept shipping.Proposed 4.x answers to #4040
htmx-2-compator an extension.htmx.cancelPolling(elt)?everyagain.every 1s for 60s?Evidence in the draft PR
Tests that pin current four-dev (no core behavior change):
everyinnerHTMLkeeps the poller, soeverycontinuesouterHTMLwithouteverystopsHX-Reswap: outerHTMLof a triggerless copy stops an innerHTML pollerDocs, what’s-new,
upgrade-check(flag286next to poll/hx-trigger), and the 2→4 skill.Not proposing merge until this discussion lands. If the room wants 286 back in core, this PR is easy to close.
All reactions