Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

watch(..., { flush: "pre" }) behaves like "sync" #5721

Closed
h-h-h-h opened this issue Apr 14, 2022 · 2 comments
Closed

watch(..., { flush: "pre" }) behaves like "sync" #5721

h-h-h-h opened this issue Apr 14, 2022 · 2 comments
Labels
❗ p4-important Priority 4: this fixes bugs that violate documented behavior, or significantly improves perf. scope: reactivity

Comments

@h-h-h-h
Copy link

h-h-h-h commented Apr 14, 2022

Version

3.2.33

Reproduction link

sfc.vuejs.org/

Steps to reproduce

  • (Just observe the output.)

What is expected?

Output:

pre, a: 2, b: 1

sync, a: 1, b: 0
sync, a: 2, b: 0
sync, a: 2, b: 1

post, a: 2, b: 1

What is actually happening?

Output (only difference is the pre lines):

pre, a: 1, b: 0
pre, a: 2, b: 0
pre, a: 2, b: 1

sync, a: 1, b: 0
sync, a: 2, b: 0
sync, a: 2, b: 1

post, a: 2, b: 1

Unfortunately, the API docs on vuejs.org don't define the behavior of "pre", "sync" and "post" (also not here). Strangely, I found more exhaustive documentation here on w3cub.com (Vue 3-related), that says:

If flush is set to 'sync', the callback will be called synchronously, as soon as the value changes.

For both 'pre' and 'post', the callback is buffered using a queue. The callback will only be added to the queue once, even if the watched value changes multiple times. The interim values will be skipped and won't be passed to the callback.

Buffering the callback not only improves performance but also helps to ensure data consistency. The watchers won't be triggered until the code performing the data updates has finished.

'sync' watchers should be used sparingly, as they don't have these benefits.

  1. This exhaustive documentation should be on vuejs.org.
  2. Judging by what the option strings seem to represent and what makes sense, this description should be correct. But, in reality, Vue behaves like "sync" when "pre" was passed and calls the callback immediately and synchronously, as console.log() calls prove.

The output for "pre", as listed before, is expected to be diffrent to the current actual output for the following reasons:

  • Triggering the watcher callback for each a mutation (a.value++) should be reserved for "sync".
  • Triggering the watcher callback for each mutation of either a or b is, in my opinion and according to my understanding, also in the realm of "sync". I'm trying to use "pre" to watch multiple sources as a whole, sources that are often, but not always, mutated together and where a watcher-callback-run after the mutation of just one source might catch an inconsistent state, which leads to undefined behavior.
    • Perhaps the AND/OR behavior of watch() also isn't defined enough when there are multiple watch sources. Without knowing specifics about other use cases, it's conceivable that both logical linkings can be desirable. The default behavior should be clearly communicated and, if need be, an additional option should be added to get the other type of logical linking of the sources.
@LinusBorg
Copy link
Member

This exhaustive documentation should be on vuejs.org.

Great Idea. Would be appreachiated if you were to make the docs team in the docs repo aware by opening an issue there.

About the issue: Behavior not expected IMHO. Interestingly, this only seems to happen if the changes happen synchronously after the watcher has been defined. If you do these changes in onMounted(), for example, you get the expected result.

Playground

@zhenzhenChange
Copy link

zhenzhenChange commented Oct 12, 2022

This issue was raised a long time ago, only then was turned to are only discussed in the docs (vuejs/docs#1154), but now since it has been solved, I thought of linking to leave a historical record.

@github-actions github-actions bot locked and limited conversation to collaborators Sep 20, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
❗ p4-important Priority 4: this fixes bugs that violate documented behavior, or significantly improves perf. scope: reactivity
Projects
None yet
Development

No branches or pull requests

3 participants