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

Implement Observable.spawn(function* (){}) #1497

Closed
sladiri opened this Issue Mar 20, 2016 · 16 comments

Comments

Projects
None yet
6 participants
@sladiri
Copy link

sladiri commented Mar 20, 2016

It seems that the spawn function is not implemented in RxJS5. As such, I cannot yield to Observables.
Our use case is to retrieve paginated data from a web-server. This is my how I can do it in RxJS4:

Rx.Observable.spawn(function* () {
  const limit = 2;
  try {
    const aprxjs = Rx.Observable.fromCallback(api);
    const lazyArr = [];
    yield aprxjs(0)
      .expand(v => v < limit ? aprxjs(v) : Rx.Observable.empty())
      .do(v => lazyArr.push(v));
  }
  catch (e) { console.log('er', e.stack); }
}).subscribe();
@benlesh

This comment has been minimized.

Copy link
Member

benlesh commented Mar 20, 2016

Thanks for pointing this out, @sladiri. We'll discuss adding this functionality, in the meantime you should be able to do this with:

Observable.from((function* () {
  yield Observable.of('foo');
}())
.mergeAll() // choose your merge strategy here.
.subscribe();
@benlesh

This comment has been minimized.

Copy link
Member

benlesh commented Mar 21, 2016

To be clearer, @sladiri, I'm not suggesting what I've put above is a replacement for spawn. Rather, it will work for your use-case. spawn is doing other things to send values retrieved from async types back into the generator as a co-routine.

I suppose the discussion here is about whether or not this belongs in this library, or if this is an interesting one-off function for supporting various async types using a generator. Just to clarify.

@staltz? @mattpodwysocki? @trxcllnt? what are your thoughts?

@staltz

This comment has been minimized.

Copy link
Member

staltz commented Mar 21, 2016

Given

var spawned = Rx.Observable.spawn(function* () {
  var v = yield thunk(12);
  var w = yield [24];
  var x = yield Rx.Observable.just(42);
  var y = yield Rx.Observable.just(56);
  var z = yield Promise.resolve(78);
  return v + w[0] + x + y + z;
});

I'd prefer to convert each of these pieces into an Observable and compose them as Observables. So I can't see much of a use for spawn if we have from(Iterator).

@sladiri

This comment has been minimized.

Copy link
Author

sladiri commented Mar 26, 2016

Thank you for the explanation. I am new to this library and I overlooked the possibility of using from().

@episodeyang

This comment has been minimized.

Copy link

episodeyang commented Mar 27, 2016

took me a while to figure out that spawn is not implemented in 5.0. Thanks for creating this issue!

I'm looking at this because I'm writing a reactive saga for a reactive redux library called luna.

@alex-okrushko

This comment has been minimized.

Copy link

alex-okrushko commented Jun 8, 2016

Lost a couple of hours trying to understand why "Property 'spawn' does not exist on type 'typeof Observable'."
It appears that the documentation is for RxJS4 exclusively and the MIGRATION doc doesn't not mention that spawn, or for that matter generate are not implemented.
Is there a documentation for RxJS5 somewhere? I'm new to this framework, so I refer the documentation a lot.

@benlesh

This comment has been minimized.

Copy link
Member

benlesh commented Jun 8, 2016

Is there a documentation for RxJS5 somewhere?

@alex-okrushko: It's a work in progress, but most of it can be found via the README on this repo, and here: http://reactivex.io/rxjs/

@benlesh

This comment has been minimized.

Copy link
Member

benlesh commented Jun 8, 2016

@jhusain this is very similar to what we were working on today at Netflix. We should definitely look at porting spawn into Rx 5.

@alex-okrushko

This comment has been minimized.

Copy link

alex-okrushko commented Jun 8, 2016

@blesh Wow, that documentation is really good (very easy to consume)! Thanks a lot!

@benlesh

This comment has been minimized.

Copy link
Member

benlesh commented Feb 21, 2017

Closing as inactive.

@benlesh benlesh closed this Feb 21, 2017

@pablocarreraest

This comment has been minimized.

Copy link

pablocarreraest commented Feb 2, 2018

hi @benlesh, in typescript the types of from is:

export declare class FromObservable<T> extends Observable<T> {
    private ish;
    private scheduler;
    constructor(ish: ObservableInput<T>, scheduler?: IScheduler);
    static create<T>(ish: ObservableInput<T>, scheduler?: IScheduler): Observable<T>;
    static create<T, R>(ish: ArrayLike<T>, scheduler?: IScheduler): Observable<R>;
    protected _subscribe(subscriber: Subscriber<T>): any;
}

so it can't create from a generator function without a type error...

maybe I'm wrong but just want to know how handle like async/await with observables. I made some observables functions that the flow depends in sequence like async / await does with promises... if you can point me to a good direction... love to hear from you 🙃

@benlesh

This comment has been minimized.

Copy link
Member

benlesh commented Feb 2, 2018

@pablocarreraest be sure you're calling your generator function: from(function* () { ... }()) (Notice the last () in there)

@pablocarreraest

This comment has been minimized.

Copy link

pablocarreraest commented Feb 3, 2018

@benlesh I try:

public findByIdOrName$ (id: string): Observable<Movie> {
 return Observable.from(function* (): IterableIterator<Movie> {
    try {
        const movie = yield this.findById$(id);
        return (movie) ? movie : yield this.findByName$(id);
    } catch (error) {
        return Observable.throw(error);
      }
   }());
}

I get a error of:

file: 'file.ts'
severity: 'Error'
message: 'Argument of type 'IterableIterator<Movie>' is not assignable to parameter of type 'ArrayLike<{}>'.
Property 'length' is missing in type 'IterableIterator<Movie>'.'
source: 'ts'

or maybe as you say I work with async / await and handle observables with toPromise()🤔

@benlesh

This comment has been minimized.

Copy link
Member

benlesh commented Feb 3, 2018

Hmm... sounds like a typings issue. This will definitely work in normal JavaScript. Try casting as Iterable<Movie>, and if all else fails, I guess any, and we'll file a separate bug

@pablocarreraest

This comment has been minimized.

Copy link

pablocarreraest commented Feb 3, 2018

with Iterable<Movie>

file: 'file.ts'
severity: 'Error'
message: 'Argument of type 'Iterable<Movie>' is not assignable to parameter of type 'ArrayLike<{}>'.
  Property 'length' is missing in type 'Iterable<Movie>'.'
source: 'ts'
code: '2345'

and with any

👍

but when I use the function with any at the first yield won't get me nothing of return in other words:

public findByIdOrName$ (id: string): Observable<Movie> {
    return Observable.from(function* (): any {
      try {
        console.log(id); // get the id or name -> beauty and the beast
        const movie = yield this.findById$(id); // function that return a observable, in here die just nothing happens
        console.log(movie); // --> nothing it don't get to this 
        return (movie) ? movie : yield this.findByName$(id); // function that return a observable
      } catch (error) {
        return Observable.throw(error);
      }
    }());
}

at console:

> beauty and the beast

I'm like 🧐>🤔>🤯>🤨 so I can't get to 😎 environment (sorry about the faces is friday)

@lock

This comment has been minimized.

Copy link

lock bot commented Jun 6, 2018

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Jun 6, 2018

thejohnfreeman added a commit to thejohnfreeman/rxjs that referenced this issue Jan 12, 2019

feat(async,spawn): add async functions for observables
A [longer version][] of the justification for this change is available
online. In brief, we're missing the observable equivalent of async
functions. Chaining operators like `map`, `filter`, and `catchError`
with observables that yield a single value is as painful as chaining
callbacks on promises. Async functions let us write asynchronous code in
a synchronous style, which is easier to read, write, and comprehend.
Short of native syntax like async/await, we can offer a decorator for
generator functions.

[longer version]: https://medium.com/@thejohnfreeman/escaping-pipeline-hell-38d962f66d31

Fixes ReactiveX#1497
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.