Giter VIP home page Giter VIP logo

Comments (10)

zenparsing avatar zenparsing commented on May 26, 2024

Thanks for raising this issue. Please check out Observable.from in the "callback-style" branch. It does something very similar to what you're asking for. In fact, I think between Observable.of and Observable.from it should cover the bases.

The big design change I made is that I introduced Symbol.observable. This works just like Symbol.iterator: for some arbitrary "observable" type, it returns an observable object. Like iterators, observables have a Symbol.observable method which just returns this.

We could add Symbol.observable to Promise.prototype as well, which would make them convertible with Observable.from.

from es-observable.

zenparsing avatar zenparsing commented on May 26, 2024

It looks like the scenarios can be mapped to from/of like this:

  1. "observablesque" => Observable.from.
  2. valueType => Observable.of
  3. iterable => Observable.from
  4. object => Observable.of
  5. promise => Observable.from (potentially)

The only issue is that you have to know whether to call from or of in advance. That makes sense to me though, because the two operations are very different from a type point of view:

Observable.from(Observable<T>) : Observable<T>
Observable.from(Iterable<T>) : Observable<T>

Observable.of(T) : Observable<T>
Observable.of(T, U) : Observable<any>
Observable.of(T, U, V) : Observable<any>
...

I think a more heuristic casting function would be useful, but maybe not appropriate for the core API?

I can see Arrays and generators mapping to Observables just fine, but Strings are iterable, and I think most of the time people will want those to be mapped into an observable of item.

Again, I don't think I'd feel comfortable adding such a heuristic. The from/of distinction seems good to me and allows users to express their intent explicitly.

For promises and single values, do we just make an observable that nexts out one value? Should it complete/return with that one value also?

That's a good question. Observable.of takes a variable number of arguments, so it makes sense to next each one and then complete with void (like all other iterable sequences).

For promises, my personal opinion is that it should next the fulfillment value and then complete with void. It's just so much easier to consume that way with the callback style:

Observable.from(promise).subscribe(
    val => console.log(`Resolved with ${ val }`), 
    err => console.log(`Boo, rejection! ${ err }`));

And it has a nice symmetry with then:

promise.then(
    val => console.log(`Resolved with ${ val }`), 
    err => console.log(`Boo, rejection! ${ err }`));

from es-observable.

benlesh avatar benlesh commented on May 26, 2024

I think there should just be one method that you can use to convert anything to an observable, personally. Perhaps that's from. of seems more specialized.

On Promise conversion

Are we still going with the return or completed path returning a value? If so, it seems like Promises would map 1:1 with something like just returning the resolved value. However, that makes composing over the Observable painful. There are really three options:

new Observable(o => {
  promise.then(x => {
     o.next(x);
     o.return();
  }, err => o.error(err));
});
new Observable(o => {
  promise.then(x => {
     o.return(x);
  }, err => o.error(err));
});
new Observable(o => {
  promise.then(x => {
     o.next(x);
     o.return(x);
  }, err => o.error(err));
});

I think 1 or 2 are acceptable. 3 seems weird. 1 makes it the easiest to compose. 2 gives more purpose to the whole "return having a value" thing, and means every Observable that has a return value could be treated somewhat like a promise.

My gut tells me the right thing to do is go with 1, and then have a specialized "ScalarObservable" that matches the signature of Observable, but only ever emits one value. That, of course doesn't need to be part of this proposal, but as a library implementor, I might just add a boolean check for an isScalar or the like so I can optimize code paths.

from es-observable.

zenparsing avatar zenparsing commented on May 26, 2024

I think there should just be one method that you can use to convert anything to an observable, personally.

I'm a little worried that if you make such an all-accepting function, it will be a breaking change to make some type T observable-ish if it was previously not observable-ish. It would cause the behavior to go from:

from(T) : Observable<T>

to:

from(observablesque<T>) : Observable<T>

My gut tells me the right thing to do is go with 1

Mine too, but maybe @jhusain has a different opinion?

from es-observable.

benjamingr avatar benjamingr commented on May 26, 2024

Definitely in favor of 1 here. If observables don't have a return value it's as simple as the fact:

 a; // value
 [a]; // array containing one value.

That said, I think it's important to keep consistency with async iterators. So observables should probably behave consistently to those.

from es-observable.

jhusain avatar jhusain commented on May 26, 2024

The breaking change hazard is real unfortunately. Under the circumstances, we should probably go with option one.

from es-observable.

benjamingr avatar benjamingr commented on May 26, 2024

@domenic can you clarify what async iterators do here so observables can align?


Based on Babel indeed 1 is the correct thing to do: http://babeljs.io/repl/#?experimental=true&evaluate=true&loose=false&spec=false&playground=false&code=async%20function*%20foo()%7B%0A%20%20yield%201%3B%0A%7D%0A%0Avar%20f%20%3D%20foo()%3B%0Af.next().then(function()%7B%0A%20%20console.log(arguments)%3B%0A%7D)%3B%0Af.next().then(function()%7B%0A%20%20console.log(arguments)%3B%0A%7D)

from es-observable.

domenic avatar domenic commented on May 26, 2024

What am I clarifying? @zenparsing is the expert on async iterators anyway as it's his proposal. Your code looks a bit suspicious in that it does yield 1 instead of return 1 but I don't have any context.

from es-observable.

benjamingr avatar benjamingr commented on May 26, 2024

@domenic ok then, apologies for the ping don't waste time on it - @zenparsing will clarify it :)

from es-observable.

benlesh avatar benlesh commented on May 26, 2024

I think Observable.from solves this adequately for now. Closing.

from es-observable.

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.