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

Subscribe callback with current value of stateful observables #190

Open
brianmhunt opened this issue Jun 23, 2018 · 16 comments
Open

Subscribe callback with current value of stateful observables #190

brianmhunt opened this issue Jun 23, 2018 · 16 comments

Comments

@brianmhunt
Copy link

It's not clear (and perhaps not defined) what should happen when stateful observables like those in Knockout and mobx and others should do when .subscribe is called.

I.e. what should happen in this sequence:

>>> const x = ko.observable('abc')
>>> x.subscribe({ next: console.log })
>>> x('def')

Should the output be abc def or just def?

I ask in particular because I'm adding TC39 support to Knockout.

@benjamingr
Copy link

I would expect x to emit abc synchronously and then emit def when the value changed.

@brianmhunt
Copy link
Author

Thanks. That's my expectation too. I'd like to be compliant with any specs, or at least consistent with other libraries.

@benjamingr
Copy link

@brianmhunt we've (I've) been dragging our feet with this for ~2 years with MobX - I think we can agree on that semantic for it. cc @mweststrate

brianmhunt added a commit to knockout/tko that referenced this issue Jun 24, 2018
…tyle subscribe

So when a TC39 style `subscribe` call is made, we trigger with the current value immediately, contrasting with the prior behaviour - namely triggering only on changes to the state.

tc39/proposal-observable#190
@mweststrate
Copy link

I would expect only def to be emitted, as, imho, you subscribe to the event of a new value to become available, and it is nice that that internal value of the observable doesn't have to be materialized immediately (for example if it is computed). Similar to how attaching in mouse move event doesn't immediate propagate with the current coordinates, however convenient that could be

That being said, personally I don't care that much, as long as it is standardized :-D.

@brianmhunt
Copy link
Author

The subscription could provide an option e.g. something like this:

obs.subscribe({
  next: () => ...
  emitCurrentState: true
})

@benjamingr
Copy link

@mweststrate I think this is similar to a computed running the function once to know dependents etc.

@brianmhunt
Copy link
Author

@mbest any thoughts on this?

@mbest
Copy link

mbest commented Jun 25, 2018

I think it should mirror the Knockout subscribe behavior, which is to only emit new changes after the subscribe call. That being said, it's often useful to have a subscribe-type interface that also processes the current value. That's of course how ko.computed works.

@appsforartists
Copy link
Contributor

This feels off-topic to me. The Observable pattern and how Knockout makes use of it are separate topics, and only the former is germane here.

It's common for stateful Observables (e.g. Subjects) to emit the last known value to new subscribers. However, that's a decision to be made at the producer level (probably Knockout in this case), not one that needs to be discussed here.

@benjamingr
Copy link

not one that needs to be discussed here.

I don't understand where this is coming from - using Symbol.observable for interoperability between consumers of the API is worth while. You have two libraries with hundreds of thousands of users debating how the language feature proposed should work for them and are asking for clarifications on how to use that feature.

To be honest - as far as I'm aware following this repo for 3+ years we never had this discussion about Symbol.observable yet. I wish more people weighed in to be honest.

I will defer to Jafar and Mark about whether or not they consider this discussion useful at the moment though.

brianmhunt added a commit to knockout/tko that referenced this issue Jun 28, 2018
* Initial support of TC39 Observable subscriptions

* tko.observable) Trigger immediately with current with TC39 `{next}`-style subscribe

So when a TC39 style `subscribe` call is made, we trigger with the current value immediately, contrasting with the prior behaviour - namely triggering only on changes to the state.

tc39/proposal-observable#190

* jsx) fix out-of-order observable insertion

* jsx) Fix arrays of new nodes not having context applied

* provider/native) Add a provider that has “pre-compiled” binding handler arguments

This will be used by the JSX utility.

* component/jsx) Support observables for Component jsx templates

Now JSX binding arguments are known at the compile-time, so this ought to work:

```js
get template () {
   return <div ko-text={this.someValue}></div>
}
```

* jsx) Add support for bindings directly referenced in JSX

Sample:

```html
 <component x={alpha}></component>
```

… will be given `params={x: alpha}`

* provider/native) Fix failure when node doesn’t have `NATIVE_BINDINGS`

* component/jsx) re-apply bindings to top-level templates

* tko.bind) Fix regression with `onValueUpdate` not working

@ctcarton

* tko.observable/computed) Have TC39 subscriptions fire immediately for observable/computed

* jsx) Fix insert of array appending instead of inserting
@brianmhunt
Copy link
Author

brianmhunt commented Jun 28, 2018

For the moment, in tko/knockout 4 alpha I've set up ko observables to emit their current state whenever a TC39-compliant subscribe call is made (i.e. an object with a next method).

I can be persuaded to change this, particularly before we end the alpha stage, but I wanted to the concept merged — even if not in its final form.

@dy
Copy link

dy commented Jun 20, 2020

@brianmhunt what if initial state is undefined? Does that still emit value?

@benjamingr
Copy link

@dy undefined is still a value, so I would expect it to be have the same as any other value.

@dy
Copy link

dy commented Jun 21, 2020

@brianmhunt I meant what if initial value is not defined, ie. value is not provided for init? That is different from undefined, I'd expect observable not to emit sync value, although that inconsistent with regular subscribe.

@brianmhunt
Copy link
Author

@dy You mean if the value of the observable had never been set?

I think the behaviour most would expect is to emit an undefined value. Is there a compelling use case for a different behaviour?

@dy
Copy link

dy commented Jan 19, 2022

I remember using that somehow implementing combined observables, not relevant anymore.
Note also that simpler signature for subscribe is also possible: obs.subscribe(onnext, onerr?, oncomplete?).
Just curious - what's the status?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants