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
Closed

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

sladiri opened this issue Mar 20, 2016 · 16 comments
Labels

Comments

@sladiri
Copy link

@sladiri 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
Copy link
Member

@benlesh 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
Copy link
Member

@benlesh 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
Copy link
Member

@staltz 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
Copy link
Author

@sladiri sladiri commented Mar 26, 2016

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

@geyang
Copy link

@geyang geyang 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
Copy link

@alex-okrushko 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
Copy link
Member

@benlesh 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
Copy link
Member

@benlesh 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
Copy link

@alex-okrushko alex-okrushko commented Jun 8, 2016

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

@benlesh
Copy link
Member

@benlesh benlesh commented Feb 21, 2017

Closing as inactive.

@benlesh benlesh closed this Feb 21, 2017
@pablocarreraest
Copy link

@pablocarreraest 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
Copy link
Member

@benlesh benlesh commented Feb 2, 2018

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

@pablocarreraest
Copy link

@pablocarreraest 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
Copy link
Member

@benlesh 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
Copy link

@pablocarreraest 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
Copy link

@lock 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
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.
Labels
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
6 participants