Giter Site home page Giter Site logo

TC39 Proposal - Observable about tko HOT 14 OPEN

knockout avatar knockout commented on May 16, 2024 3
TC39 Proposal - Observable

from tko.

Comments (14)

far-blue avatar far-blue commented on May 16, 2024 2

I've put together an example extender for ko.observable that works with most.js:
https://gist.github.com/far-blue/a652029beaaf9b7a97455c0d9cdd8678

from tko.

brianmhunt avatar brianmhunt commented on May 16, 2024 1

Smart, thanks for linking

from tko.

brianmhunt avatar brianmhunt commented on May 16, 2024 1

Yeah, this requires some thought, I believe. These are the priorities that come to mind:

  1. Maintain backwards compat
  2. Add new functionality for compatibility with TC
  3. Polyfill TC as needed (passing the proposal's tests)
  4. Add new functionality to supplement TC in ways that make sense for (t)KO (e.g. if we can reduce code duplication)

We've also got some code now that has Observable; we'll need to be cautious not to add more, owing to the name collision.

So the ko.Observable will become

  1. an TC-39 Observable, and
  2. also be the generator reader function i.e. when called with one argument it generates/triggers the subscriptions, when called with no arguments it returns the latest value.
  3. Lots of other things. :)

The ko subscriptions will need:

  1. an unsubscribe method. (=== dispose)
  2. a closed property

from tko.

krnlde avatar krnlde commented on May 16, 2024

Could be done via:

import {observable as Observable} from 'tko';

const x = new Observable(/* TODO: API should be concise with the spec */);

from tko.

brianmhunt avatar brianmhunt commented on May 16, 2024

There are some problems. For example, the TC Observable is not a function; the Knockout observable is essentially both the entity being observed and the observable class.

Which doesn't make it not doable, just interesting. :)

from tko.

brianmhunt avatar brianmhunt commented on May 16, 2024

If we're going to be making an ES6 class of the TKO Observable (and arguably we should), here's a discussion maybe worth noting: http://stackoverflow.com/questions/36871299/how-to-extend-function-with-es6-classes

from tko.

krnlde avatar krnlde commented on May 16, 2024

Maybe the ko.observable of the future is going to be obsolete and knockout will be the 2way databinding layer together with some utility functionality like computeds, validation, mapping, extend, susbscribable etc.

from tko.

krnlde avatar krnlde commented on May 16, 2024

Great thoughts! I'll need some time to think about that too :)

from tko.

brianmhunt avatar brianmhunt commented on May 16, 2024

@far-blue I'm copying your issue from tko.observable (and closing tko.observable issues as we've since/just moved to a monorepo here), as:

There's a standards proposal for ES8 (https://github.com/tc39/proposal-observable) which takes the bare bones of the observer/subscriber pattern from most.js, rxjs, xstream, zen-observable etc. to provide some compatibility in the same way Promises became standardised.

I don't think KO's observer/subscriber pattern is very far away from the suggested standard and it would be cool if KO observables could interop.

As an example of how these libraries work, I found this tutorial helpful :) https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

As you can see, where the tutorial talks about streams of DOM events or subscribers updating the DOM, KO could slot in very neatly :)

from tko.

far-blue avatar far-blue commented on May 16, 2024

In the terminology used by libraries such as most.js, ko's observables are closest to 'Properties' rather than streams because they hold on to their last value. I'm not convinced KO needs to adopt Observables entirely, simply provide interop - at least to start with.

If you think about how KO would interop with Observables (aka 'streams'), I see three situations.

Firstly, a ko.observable could subscribe to a stream. the ko.observable would present as an Observer and so would need start(), next(), error() and complete() methods although error() and complete() methods could throw and be ignored respectively. start() and next() methods would simply update the value like the setter and trigger a hasMutated. This would work the same for writable computeds.

Secondly, a ko.observable would need to be observable through subscription. I'm not sure the constructor, the statics or the callebacks-based subscribe in the proposal are needed in this context and ko already has the concept of subscribe so extending it to support subscribing with an observer should be simple enough. The same applies to computeds.

Considering observableArrays, I'm not sure it would be a good idea to try to make them into streams. Instead, I suggest if an observableArray subscribed to a stream then it would simply update to match the latest value and expect the data values on the stream to already be arrays. In the same way, subscribing to an observableArray would mean the new state of the array was the pushed to the subscriber when the observableArray was changed. In the terminology of most.js and rxjs which treat arrays (Iterables) and promises as types of streams, an observableArray would generate a metastream but it's then up to the subscriber to deal with it.

In theory it also sounds nice to maybe have a stream of changes for an observableArray but then you'd need to define the structure for each event (add, remove, update). If you did, then you could also subscribe the observableArray to such a stream and have it apply the changes.

In all cases, I don't believe the standards proposal requires the Observer or Observable to be objects. As long as the methods are supported everything should work. As such, it should work if the required methods were in the function prototype for the functions returned by ko.observable() etc.

from tko.

far-blue avatar far-blue commented on May 16, 2024

To try and give some code examples.

First, a ko.observable tracking an Observable:

var foo = ko.observable();
var stream = Observable.from([1, 2, 3, 4]);
var subscriptionHandler = stream.subscribe(foo);

foo will be set to 1 then 2, then 3, then 4 in sequence.

An Observable from a ko.observable using from():

var foo = ko.observable();
var stream = Observable.from(foo);

from tko.

far-blue avatar far-blue commented on May 16, 2024

Just to comment on the gist. Clearly things would be neater if done natively rather than as an extender but the gist proves the interop suggestion. In the end it turns out (at least for most.js) observe() accepts a function that is called on each update of the thing it is observing so for the demo I just rely on a ko.observable being a function and passing it straight to observe(). For proper spec. interop it would prob. be sensible to have the Observer interface of next() and error() methods (next.js docs suggest complete() is deprecated) so the subscribe() method in the TC can be used rather than observe().

from tko.

far-blue avatar far-blue commented on May 16, 2024

I've investigated the ability to subscribe() and compatibility seems to come down to each library's interpretation of 'object'. RxJS and ZenObservable consider a function to be an object while most.js currently doesn't. ZenObservable does the check as Object(subscriber) === subscriber while most.js does typeof subscriber === 'object'. I think ZenObservable's approach to be better and will submit an issue for most.js.

I've updated the gist to demonstrate how subscribe() could work if most.js followed ZenObservable's approach but that means the gist now only works if you update line 1075 of most.js (non-minified!) from if (subscriber == null || typeof subscriber !== 'object') { to if (subscriber == null || Object(subscriber) !== subscriber) {

The gist also renamed what was the "Observable" extender to "Observer" and created a second extender for the actual "Observable".

from tko.

far-blue avatar far-blue commented on May 16, 2024

FYI, most.js v1.4.0 includes my patch to allow functions as subscribers :)

from tko.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.