Provide onInvalidate to register callbacks to call when Watcher gets updated (invalidated)
See original GitHub issueWhat problem does this feature solve?
Sometimes inside a Vue reactive context (Watcher
) you have to read data from an external source. You might have to manage resource consumption of that external source so a way to know when is current has been notified of an update in a dependency is useful because you could cancel the external source. If current watcher is already pending a run there is no point in waiting for an external source to notify as well.
I have encountered this problem when I was implementing a reactive time formatting functions. In that case I setup a timeout until the next update to the formatted string (if currently timestamp is displayed as 1 hour ago
the next update is in one hour to display 2 hours ago
). But if something else triggers an update (like timestmap changing in the source) there is no point in that timeout to still be around. So ideally, that timeout should be cleared. But there is no way for that currently.
I could implement this with a reactive data source which I would modify every second and then in the formatting function use the data source to compute the formatted string. But that would be very inefficient because it would rerun that formatting function every second when it would have to be rerun only in an hour. I could design it so that every formatting call registers its own data source which is updated only at a particular interval, but managing that would be very complex because it would not really be at regular intervals but the interval changes (for example, when string gets changed from 59 minutes ago
to 1 hour ago
).
What does the proposed API look like?
I would suggest Watcher
gets a concept of invalidated
state. That state would be set to true
on the first update()
on the watcher and reset back to false
on the first next get()
. If update()
is called multiple times before get()
is called, watcher continues to be in invalidated==true
state.
Having that concept, I would suggest Vue.util.onInvalidate(callback)
function which would register a callback for the current watcher context (Dep.target
). That callback would be called when watcher gets invalidated (the first time update()
is called). If during onInvalidate
is called on a watcher which is already invalidated, the callback would be called immediately.
Any callback
is called only once. You have to re-register them by calling onInvalidate
again if you want to get it called again.
Moreover, on watcher teardown, any pending onInvalidate
callbacks would be called as well.
I have implemented this API inside this package, but I would prefer if it was added to the official API.
Issue Analytics
- State:
- Created 5 years ago
- Comments:8 (8 by maintainers)
Top GitHub Comments
It’s not - will probably be in the next minor
I managed to implement it by monkey-patching Vue. I do not think this is very nice.
Oh, this is already supported?