Closed zoomclub closed 7 years ago
The main purpose here is to consume Observables in an automated way to optimize real-time data usage and toggle subscriptions only when components really need it.
RxJS is a great library, don't get me wrong, but why should we introduce it if Vue's watchers are good enough for the job? There is no reason to make things harder and more complicated than they need to be.
Plus, you get all the features of a Vue instance to create computed properties and such, all of which is already available with Vue core without any additional library.
@Akryum Thanks for the clarification. There just seems to be many similar approaches already, for instance a router route can also be used to manage data for a component. Seems the options for data IO are fragmented IMO. Had a look at FeathersJS, seems robust and consistent.
@Frizi Are Vue's watchers good enough for the job? I think they are useful yet they can not give me the toolbox of operators that RxJS provides. For many of my tools RxJS is required, to try and rebuild the required operators with Vue is simply not a good use of production time.
@Akryum I agree a Vue instance has a lot to offer yet it is not a API that provides a full rack of operators that can be piped together like legos to build almost any kind of process required.
Using external reactive data sources efficiently has been a pain point when working with meteor or apollo and vuex. I created this package precisely to solve this problem, and it is not intended to be the silver bullet for other data processing which I think dedicated libraries like highland.js are better at. BTW you could use both vue-supply & RxJS if you wish.
Also, I chose to go with Vue instance to reduce the introduction of new concepts, since vue-supply just basically uses standard data/computed properties and methods. The other big advantage is that you can directly use things like vue-meteor-tracker inside a Supply, since it's just a simple Vue instance after all:
import { Supply } from 'vue-supply'
import { Messages } from '../collections'
export default new Vue({
data () {
return {
messageList: [],
}
},
// Realtime data from Meteor
// special option provided by vue-meteor-tracker
meteor: {
messageList () {
return Messages.find({}, {
$sort: { date: -1 },
})
},
},
// Automatic activation
methods: {
activate () {
// Meteor subscription
// Special method provided by vue-meteor-tracker
this.messagesSub = this.$subscribe('private-messages')
},
deactivate () {
// Special method provided by vue-meteor-tracker
this.$stopHandle(this.messagesSub)
},
},
})
And inside a component:
import { use } from 'vue-supply'
import PrivateMessages from 'supplies/private-messages'
export default {
// Will automatically start and stop the necessary subscriptions
mixins: [use(PrivateMessages)],
computed: {
privateMessages () {
return PrivateMessages.messageList
}
}
}
I think declaring data usage at a component-level instead of routes helps decoupling the components from the structure of your app, avoiding errors like forgetting to add one of the hundred required subscriptions for a page (it simpler to reason about what the data is consumed by a component when looking at it directly with everything at a glance instead of a route code far away in the project), maintaining and evolving those components (you don't need to worry about changing all the potential routes where this component potentially is).
@zoomclub Did we answer your questions?
Not sure, strikes me as a take on the basic un/subscribe concept. Is the de/activation automatic only when a component is first created? Can de/activation happen at runtime? Can the source data stream be swapped with a different source during runtime?
These runtime options are likely not possible due to how the reactivity of a vue-instance works at this present time, according to https://vuejs.org/v2/guide/reactivity.html
Still an open issue, can close it if you prefer? At this point I'd just have a few things to clarify:
• For my scenario I would need the de/activation to also be possible at runtime. • Maybe look at vue-rx for some beautiful automatic un/subscribe solution. • Realize that vue-rx does all it's un/subscribe based on component lifecycle too. • Find the best way to add runtime de/activation un/subscribe in auto reactive frameworks.
You have a few ways to manually use a Supply.
The low-level way with grasp()
and release()
:
import TestResource from 'supply/test-resource'
console.log(TestResource.consumers) // 0
TestResource.grasp()
console.log(TestResource.consumers) // 1
// Wait for the supply to be ready (pending subscriptions, ...)
await TestResource.ensureReady()
// Use the data here
console.log(TestResource.someData)
TestResource.release()
The high-level way with consume
:
import { consume } from 'vue-supply'
import TestResource from 'supply/test-resource'
// This will grasp and wait for the supply to be 'ready'
const release = await consume(TestResource)
// Use the data here
console.log(TestResource.someData)
// When you are done with the supply, release it
release()
Thanks again for the clarification. A major aim of mine is to simplify and it seems that it takes a lot of vigilance to keep it that way, I'm a proponent of RxJS for this very reason. I'm past the valley of decision on this one so I'll close the issue and as they say, catch you on the flip side 💯
Is the main purpose here to toggle a data source? If I'm grasping the intent then why not use Observables and Observers?
Using a Vue instance might be observable-ish, but introduces yet more concepts IMO and misses out on the rich paradigm and API that stream libraries like RxJS already provide.