Conversation
This PR introduce a new behavior boolean attribute, `preserve-order`. This attribute is used by behaviors that "fetch" content, i.e. anytime there's a `href` attribute set, with an update action such as `replace`, `replace-inner`, etc. When present, we compute an unique id before the request is emitted, and store it on an attribute of the target element. When the response arrives, we read the attribute of the target element and compare it to the one we generated before the request was sent. If the attribute is set with a value that's different from the one set before the request, we assume this means another request/response cycle took place, and the response we're presently dealing with is "outdated", so we discard it.
"cancel-stale-requests" or "discard-stale-requests" might be more descriptive? |
|
I was curious how this is implemented in htmx. Looks like that library stores a queue of requests, and using an attribute there are different strategies for managing the queue if the element issues multiple requests. See the docs here: https://htmx.org/attributes/hx-sync/ Do you think a similar approach could work in Hyperview? |
|
Source code from htmx to deal with this: https://github.com/bigskysoftware/htmx/blob/master/src/htmx.js#L2980 |
|
Looking at the htmx implementation a bit more, I think perhaps we could support this as follows: Introduce two new optional behavior attributes:
Over time, we can add queuing support as well if we think it's necessary. Implementation:
We will need to update the return type of |
…aviors (#1243) Adding request synchronization as [described here](#736 (comment)). This will help prevent issues where responses can complete out-of-order from the requests. Synchronization works on behaviors that make HTTP requests. Support is added through two behaviors: - `sync-id`: An ID used to synchronize requests. All requests with this ID will be subject to the sync method. - `sync-method`. One of `drop` (default) or `replace`: - if `drop`, subsequent requests with the same sync ID will not be made if there is a request currently in-flight - if `replace`, subsequent requests will be made. However, only the response of the last will be processed, the other responses will be dropped and treated as a no-op. ### Implementation The fetch API in React Native does not support cancellation with a signal. So instead, we need to track the current request for a given sync ID, and ignore responses from other requests (depending on sync method). - Add support for extracting and passing along the `sync-id` and `sync-method` attributes. - In `parser.ts`, update the logic that makes requests to support optional synchronization. - If `syncId` is provided, store request promises in a map, keyed by `syncId` - Logic based on `syncMethod` is implemented around the fetch logic. - `drop` method is processed before the request is made, potentially returning a `NO_OP` if there is another request in flight for `syncId`. - `replace` method is processed when the response is received, potentially returning a `NO_OP` if there's a newer request in flight for `syncId`. ### Other changes - [x] Updated demo with new "sync" screen that shows the `replace` method in action. Uses a dynamic response that delays responses by a random amount, to stress test the sync capabilities. - [x] Updated schema with the new attributes. - [ ] Update website docs
|
Superceded with syncing implementation |
This PR introduce a new behavior boolean attribute,
preserve-order. This attribute is used by behaviors that "fetch" content, i.e. anytime there's ahrefattribute set, with an update action such asreplace,replace-inner, etc. When present, we compute a unique id before the request is emitted, and store it on an attribute of the target element. When the response arrives, we read the attribute of the target element and compare it to the one we generated before the request was sent. If the attribute is set with a value that's different from the one set before the request, we assume this means another request/response cycle took place, and the response we're presently dealing with is "outdated", so we discard it.To be discussed: